From nobody Sun Apr 28 12:04:37 2024 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 1504286625607650.7185707922748; Fri, 1 Sep 2017 10:23:45 -0700 (PDT) Received: from localhost ([::1]:51238 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfU-0005qV-FM for importer@patchew.org; Fri, 01 Sep 2017 13:23:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36053) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpde-0004dw-73 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:21:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpdc-0001r2-Gh for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:21:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53964) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpdY-0001mW-Bb; Fri, 01 Sep 2017 13:21:44 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3BB83C057FA1; Fri, 1 Sep 2017 17:21:43 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7494B62929; Fri, 1 Sep 2017 17:21:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3BB83C057FA1 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:04 +0200 Message-Id: <1504286483-23327-2-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 01 Sep 2017 17:21:43 +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] [PATCH v7 01/20] hw/arm/smmu-common: smmu base device and datatypes 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, wtownsen@redhat.com 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" The patch introduces the smmu base device and class for the ARM smmu. Devices for specific versions will be derived from this base device. We also introduce some important datatypes. Signed-off-by: Eric Auger Signed-off-by: Prem Mallappa --- v3 -> v4: - added smmu_find_as_from_bus_num - SMMU_PCI_BUS_MAX and SMMU_PCI_DEVFN_MAX in smmu-common header - new fields in SMMUState: - iommu_ops, smmu_as_by_busptr, smmu_as_by_bus_num - add aa64[] field in SMMUTransCfg v3: - moved the base code in a separate patch to ease the review. - clearer separation between base class and smmuv3 class - translate_* only implemented as class methods --- default-configs/aarch64-softmmu.mak | 1 + hw/arm/Makefile.objs | 1 + hw/arm/smmu-common.c | 58 +++++++++++++++++++ include/hw/arm/smmu-common.h | 108 ++++++++++++++++++++++++++++++++= ++++ 4 files changed, 168 insertions(+) create mode 100644 hw/arm/smmu-common.c create mode 100644 include/hw/arm/smmu-common.h diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-= softmmu.mak index 2449483..83a2932 100644 --- a/default-configs/aarch64-softmmu.mak +++ b/default-configs/aarch64-softmmu.mak @@ -7,3 +7,4 @@ CONFIG_AUX=3Dy CONFIG_DDC=3Dy CONFIG_DPCD=3Dy CONFIG_XLNX_ZYNQMP=3Dy +CONFIG_ARM_SMMUV3=3Dy diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index a2e56ec..5b2d38d 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -19,3 +19,4 @@ obj-$(CONFIG_FSL_IMX31) +=3D fsl-imx31.o kzm.o obj-$(CONFIG_FSL_IMX6) +=3D fsl-imx6.o sabrelite.o obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_soc.o aspeed.o obj-$(CONFIG_MPS2) +=3D mps2.o +obj-$(CONFIG_ARM_SMMUV3) +=3D smmu-common.o diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c new file mode 100644 index 0000000..56608f1 --- /dev/null +++ b/hw/arm/smmu-common.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U= SA. + * + * Author: Prem Mallappa + * + */ + +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "trace.h" +#include "exec/target_page.h" +#include "qom/cpu.h" + +#include "qemu/error-report.h" +#include "hw/arm/smmu-common.h" + +static void smmu_base_instance_init(Object *obj) +{ +} + +static void smmu_base_class_init(ObjectClass *klass, void *data) +{ +} + +static const TypeInfo smmu_base_info =3D { + .name =3D TYPE_SMMU_DEV_BASE, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(SMMUState), + .instance_init =3D smmu_base_instance_init, + .class_data =3D NULL, + .class_size =3D sizeof(SMMUBaseClass), + .class_init =3D smmu_base_class_init, + .abstract =3D true, +}; + +static void smmu_base_register_types(void) +{ + type_register_static(&smmu_base_info); +} + +type_init(smmu_base_register_types) + diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h new file mode 100644 index 0000000..38cd18f --- /dev/null +++ b/include/hw/arm/smmu-common.h @@ -0,0 +1,108 @@ +/* + * ARM SMMU Support + * + * Copyright (C) 2015-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMU_COMMON_H +#define HW_ARM_SMMU_COMMON_H + +#include +#include "hw/pci/pci.h" + +#define SMMU_PCI_BUS_MAX 256 +#define SMMU_PCI_DEVFN_MAX 256 + +/* + * Page table walk generic errors + * At the moment values match SMMUv3 event numbers though + */ +typedef enum { + SMMU_TRANS_ERR_NONE =3D 0x0, + SMMU_TRANS_ERR_WALK_EXT_ABRT =3D 0x1, /* Translation walk external ab= ort */ + SMMU_TRANS_ERR_TRANS =3D 0x10, /* Translation fault */ + SMMU_TRANS_ERR_ADDR_SZ, /* Address Size fault */ + SMMU_TRANS_ERR_ACCESS, /* Access fault */ + SMMU_TRANS_ERR_PERM, /* Permission fault */ + SMMU_TRANS_ERR_TLB_CONFLICT =3D 0x20, /* TLB Conflict */ +} SMMUTransErr; + +/* + * Generic structure populated by derived SMMU devices + * after decoding the configuration information and used as + * input to the page table walk + */ +typedef struct SMMUTransCfg { + hwaddr input; /* input address */ + hwaddr output; /* Output address */ + int stage; /* translation stage */ + uint32_t oas; /* output address width */ + uint32_t tsz; /* input range, ie. 2^(64 -tnsz)*/ + uint64_t ttbr; /* TTBR address */ + uint32_t granule_sz; /* granule page shift */ + bool aa64; /* arch64 or aarch32 translation table */ + int initial_level; /* initial lookup level */ + bool disabled; /* smmu is disabled */ + bool bypassed; /* stage is bypassed */ +} SMMUTransCfg; + +typedef struct SMMUDevice { + void *smmu; + PCIBus *bus; + int devfn; + IOMMUMemoryRegion iommu; + AddressSpace as; +} SMMUDevice; + +typedef struct SMMUNotifierNode { + SMMUDevice *sdev; + QLIST_ENTRY(SMMUNotifierNode) next; +} SMMUNotifierNode; + +typedef struct SMMUPciBus { + PCIBus *bus; + SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically allo= c */ +} SMMUPciBus; + +typedef struct SMMUState { + /* */ + SysBusDevice dev; + char *mrtypename; + MemoryRegion iomem; + + GHashTable *smmu_as_by_busptr; + SMMUPciBus *smmu_as_by_bus_num[SMMU_PCI_BUS_MAX]; + QLIST_HEAD(, SMMUNotifierNode) notifiers_list; + +} SMMUState; + +typedef int (*smmu_page_walk_hook)(IOMMUTLBEntry *entry, void *private); + +typedef struct { + /* */ + SysBusDeviceClass parent_class; +} SMMUBaseClass; + +#define TYPE_SMMU_DEV_BASE "smmu-base" +#define SMMU_SYS_DEV(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_SMMU_DEV_BAS= E) +#define SMMU_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_SMMU_DEV_BASE) +#define SMMU_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_SMMU_DEV_BASE) + +#endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504286643160869.5853471766738; Fri, 1 Sep 2017 10:24:03 -0700 (PDT) Received: from localhost ([::1]:51243 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfl-000649-U5 for importer@patchew.org; Fri, 01 Sep 2017 13:24:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36200) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpds-0004rO-Pt for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpdn-00024r-Pe for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:04 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51300) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpdl-000209-0t; Fri, 01 Sep 2017 13:21:57 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 051D07EA9F; Fri, 1 Sep 2017 17:21:56 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9300652FA0; Fri, 1 Sep 2017 17:21:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 051D07EA9F Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:05 +0200 Message-Id: <1504286483-23327-3-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 01 Sep 2017 17:21:56 +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] [PATCH v7 02/20] hw/arm/smmu-common: IOMMU memory region and address space setup 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, wtownsen@redhat.com 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" We enumerate all the PCI devices attached to the SMMU and initialize an associated IOMMU memory region and address space. This happens on SMMU base instance init. Those info are stored in SMMUDevice objects. The devices are grouped according to the PCIBus they belong to. A hash table indexed by the PCIBus poinet is used. Also an array indexed by the bus number allows to find the list of SMMUDevices. Signed-off-by: Eric Auger --- hw/arm/smmu-common.c | 89 ++++++++++++++++++++++++++++++++++++++++= ++++ include/hw/arm/smmu-common.h | 6 +++ 2 files changed, 95 insertions(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 56608f1..3e67992 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -30,8 +30,97 @@ #include "qemu/error-report.h" #include "hw/arm/smmu-common.h" =20 +/******************/ +/* Infrastructure */ +/******************/ + +static inline gboolean smmu_uint64_equal(gconstpointer v1, gconstpointer v= 2) +{ + return *((const uint64_t *)v1) =3D=3D *((const uint64_t *)v2); +} + +static inline guint smmu_uint64_hash(gconstpointer v) +{ + return (guint)*(const uint64_t *)v; +} + +SMMUPciBus *smmu_find_as_from_bus_num(SMMUState *s, uint8_t bus_num) +{ + SMMUPciBus *smmu_pci_bus =3D s->smmu_as_by_bus_num[bus_num]; + + if (!smmu_pci_bus) { + GHashTableIter iter; + + g_hash_table_iter_init(&iter, s->smmu_as_by_busptr); + while (g_hash_table_iter_next(&iter, NULL, (void **)&smmu_pci_bus)= ) { + if (pci_bus_num(smmu_pci_bus->bus) =3D=3D bus_num) { + s->smmu_as_by_bus_num[bus_num] =3D smmu_pci_bus; + return smmu_pci_bus; + } + } + } + return smmu_pci_bus; +} + +static AddressSpace *smmu_find_add_as(PCIBus *bus, void *opaque, int devfn) +{ + SMMUState *s =3D opaque; + uintptr_t key =3D (uintptr_t)bus; + SMMUPciBus *sbus =3D g_hash_table_lookup(s->smmu_as_by_busptr, &key); + SMMUDevice *sdev; + + if (!sbus) { + uintptr_t *new_key =3D g_malloc(sizeof(*new_key)); + + *new_key =3D (uintptr_t)bus; + sbus =3D g_malloc0(sizeof(SMMUPciBus) + + sizeof(SMMUDevice *) * SMMU_PCI_DEVFN_MAX); + sbus->bus =3D bus; + g_hash_table_insert(s->smmu_as_by_busptr, new_key, sbus); + } + + sdev =3D sbus->pbdev[devfn]; + if (!sdev) { + char *name =3D g_strdup_printf("%s-%d-%d", + s->mrtypename, + pci_bus_num(bus), devfn); + sdev =3D sbus->pbdev[devfn] =3D g_malloc0(sizeof(SMMUDevice)); + + sdev->smmu =3D s; + sdev->bus =3D bus; + sdev->devfn =3D devfn; + + memory_region_init_iommu(&sdev->iommu, sizeof(sdev->iommu), + s->mrtypename, + OBJECT(s), name, 1ULL << 48); + address_space_init(&sdev->as, + MEMORY_REGION(&sdev->iommu), name); + } + + return &sdev->as; +} + +static void smmu_init_iommu_as(SMMUState *s) +{ + PCIBus *pcibus =3D pci_find_primary_bus(); + + if (pcibus) { + pci_setup_iommu(pcibus, smmu_find_add_as, s); + } else { + error_report("No PCI bus, SMMU is not registered"); + } +} + static void smmu_base_instance_init(Object *obj) { + SMMUState *s =3D SMMU_SYS_DEV(obj); + + memset(s->smmu_as_by_bus_num, 0, sizeof(s->smmu_as_by_bus_num)); + + s->smmu_as_by_busptr =3D g_hash_table_new_full(smmu_uint64_hash, + smmu_uint64_equal, + g_free, g_free); + smmu_init_iommu_as(s); } =20 static void smmu_base_class_init(ObjectClass *klass, void *data) diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 38cd18f..20f3fe6 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -105,4 +105,10 @@ typedef struct { #define SMMU_DEVICE_CLASS(klass) \ OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_SMMU_DEV_BASE) =20 +SMMUPciBus *smmu_find_as_from_bus_num(SMMUState *s, uint8_t bus_num); + +static inline uint16_t smmu_get_sid(SMMUDevice *sdev) +{ + return ((pci_bus_num(sdev->bus) & 0xff) << 8) | sdev->devfn; +} #endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504286781782151.1779417112151; Fri, 1 Sep 2017 10:26:21 -0700 (PDT) Received: from localhost ([::1]:51275 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnphz-0008Eb-Lm for importer@patchew.org; Fri, 01 Sep 2017 13:26:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36284) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpe0-0004x2-H2 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpdv-0002CZ-Sj for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:12 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55804) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpdq-00026b-5L; Fri, 01 Sep 2017 13:22:02 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2D22520B17; Fri, 1 Sep 2017 17:22:01 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5E13762929; Fri, 1 Sep 2017 17:21:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2D22520B17 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:06 +0200 Message-Id: <1504286483-23327-4-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 01 Sep 2017 17:22:01 +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] [PATCH v7 03/20] hw/arm/smmu-common: smmu_read/write_sysmem 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, wtownsen@redhat.com 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" Those two functions will be used to access configuration data (STE, CD) and page table entries in guest RAM. Signed-off-by: Eric Auger --- hw/arm/smmu-common.c | 37 +++++++++++++++++++++++++++++++++++++ include/hw/arm/smmu-common.h | 5 +++++ 2 files changed, 42 insertions(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 3e67992..2a94547 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -30,6 +30,43 @@ #include "qemu/error-report.h" #include "hw/arm/smmu-common.h" =20 +inline MemTxResult smmu_read_sysmem(dma_addr_t addr, void *buf, dma_addr_t= len, + bool secure) +{ + MemTxAttrs attrs =3D {.unspecified =3D 1, .secure =3D secure}; + + switch (len) { + case 4: + *(uint32_t *)buf =3D ldl_le_phys(&address_space_memory, addr); + break; + case 8: + *(uint64_t *)buf =3D ldq_le_phys(&address_space_memory, addr); + break; + default: + return address_space_rw(&address_space_memory, addr, + attrs, buf, len, false); + } + return MEMTX_OK; +} + +inline void +smmu_write_sysmem(dma_addr_t addr, void *buf, dma_addr_t len, bool secure) +{ + MemTxAttrs attrs =3D {.unspecified =3D 1, .secure =3D secure}; + + switch (len) { + case 4: + stl_le_phys(&address_space_memory, addr, *(uint32_t *)buf); + break; + case 8: + stq_le_phys(&address_space_memory, addr, *(uint64_t *)buf); + break; + default: + address_space_rw(&address_space_memory, addr, + attrs, buf, len, true); + } +} + /******************/ /* Infrastructure */ /******************/ diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 20f3fe6..a5999b0 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -111,4 +111,9 @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev) { return ((pci_bus_num(sdev->bus) & 0xff) << 8) | sdev->devfn; } + +MemTxResult smmu_read_sysmem(dma_addr_t addr, void *buf, + dma_addr_t len, bool secure); +void smmu_write_sysmem(dma_addr_t addr, void *buf, dma_addr_t len, bool se= cure); + #endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504286814676696.5197613685843; Fri, 1 Sep 2017 10:26:54 -0700 (PDT) Received: from localhost ([::1]:51279 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpiX-0000OV-HB for importer@patchew.org; Fri, 01 Sep 2017 13:26:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36340) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpe7-00053k-79 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpe1-0002Ip-3y for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41248) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpdv-0002BU-Hy; Fri, 01 Sep 2017 13:22:07 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 89FE67E454; Fri, 1 Sep 2017 17:22:06 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8413F52FA0; Fri, 1 Sep 2017 17:22:01 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 89FE67E454 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:07 +0200 Message-Id: <1504286483-23327-5-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 01 Sep 2017 17:22:06 +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] [PATCH v7 04/20] hw/arm/smmu-common: VMSAv8-64 page table walk 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, wtownsen@redhat.com 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 implements the page table walk for VMSAv8-64. The page table walk function is devised to walk the tables for a range of IOVAs and to call a callback for each valid leaf entry (frame or block). smmu_page_walk_level_64() handles the walk from a specific level. The advantage of using recursivity is one easily skips invalid entries at any stage. Only if the entry of level n is valid then we walk the level n+1, otherwise we jump to the next index of level n. Walk for an IOVA range will be used for SMMU memory region custom replay. Translation function uses the same function for a granule. Signed-off-by: Eric Auger --- v6 -> v7: - fix wrong error handling in walk_page_table - check perm in smmu_translate v5 -> v6: - use IOMMUMemoryRegion - remove initial_lookup_level() - fix block replay v4 -> v5: - add initial level in translation config - implement block pte - rename must_translate into nofail - introduce call_entry_hook - small changes to dynamic traces - smmu_page_walk code moved from smmuv3.c to this file - remove smmu_translate* v3 -> v4: - reworked page table walk to prepare for VFIO integration (capability to scan a range of IOVA). Same function is used for translate for a single iova. This is largely inspired from intel_iommu.c - as the translate function was not straightforward to me, I tried to stick more closely to the VMSA spec. - remove support of nested stage (kernel driver does not support it anyway) - use error_report and trace events - add aa64[] field in SMMUTransCfg --- hw/arm/smmu-common.c | 343 +++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/smmu-internal.h | 105 +++++++++++++ hw/arm/trace-events | 12 ++ include/hw/arm/smmu-common.h | 4 + 4 files changed, 464 insertions(+) create mode 100644 hw/arm/smmu-internal.h diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 2a94547..f476120 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -29,6 +29,349 @@ =20 #include "qemu/error-report.h" #include "hw/arm/smmu-common.h" +#include "smmu-internal.h" + +/*************************/ +/* VMSAv8-64 Translation */ +/*************************/ + +/** + * get_pte - Get the content of a page table entry located in + * @base_addr[@index] + */ +static uint64_t get_pte(dma_addr_t baseaddr, uint32_t index) +{ + uint64_t pte; + + if (smmu_read_sysmem(baseaddr + index * sizeof(pte), + &pte, sizeof(pte), false)) { + error_report("can't read pte at address=3D0x%"PRIx64, + baseaddr + index * sizeof(pte)); + pte =3D (uint64_t)-1; + return pte; + } + trace_smmu_get_pte(baseaddr, index, baseaddr + index * sizeof(pte), pt= e); + /* TODO: handle endianness */ + return pte; +} + +/* VMSAv8-64 Translation Table Format Descriptor Decoding */ + +#define PTE_ADDRESS(pte, shift) (extract64(pte, shift, 47 - shift) << shif= t) + +/** + * get_page_pte_address - returns the L3 descriptor output address, + * ie. the page frame + * ARM ARM spec: Figure D4-17 VMSAv8-64 level 3 descriptor format + */ +static inline hwaddr get_page_pte_address(uint64_t pte, int granule_sz) +{ + return PTE_ADDRESS(pte, granule_sz); +} + +/** + * get_table_pte_address - return table descriptor output address, + * ie. address of next level table + * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor f= ormats + */ +static inline hwaddr get_table_pte_address(uint64_t pte, int granule_sz) +{ + return PTE_ADDRESS(pte, granule_sz); +} + +/** + * get_block_pte_address - return block descriptor output address and bloc= k size + * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor f= ormats + */ +static hwaddr get_block_pte_address(uint64_t pte, int level, int granule_s= z, + uint64_t *bsz) +{ + int n; + + switch (granule_sz) { + case 12: + if (level =3D=3D 1) { + n =3D 30; + } else if (level =3D=3D 2) { + n =3D 21; + } else { + goto error_out; + } + break; + case 14: + if (level =3D=3D 2) { + n =3D 25; + } else { + goto error_out; + } + break; + case 16: + if (level =3D=3D 2) { + n =3D 29; + } else { + goto error_out; + } + break; + default: + goto error_out; + } + *bsz =3D 1 << n; + return PTE_ADDRESS(pte, n); + +error_out: + + error_report("unexpected granule_sz=3D%d/level=3D%d for block pte", + granule_sz, level); + *bsz =3D 0; + return (hwaddr)-1; +} + +static int call_entry_hook(uint64_t iova, uint64_t mask, uint64_t gpa, + int perm, smmu_page_walk_hook hook_fn, void *pr= ivate) +{ + IOMMUTLBEntry entry; + int ret; + + entry.target_as =3D &address_space_memory; + entry.iova =3D iova & mask; + entry.translated_addr =3D gpa; + entry.addr_mask =3D ~mask; + entry.perm =3D perm; + + ret =3D hook_fn(&entry, private); + if (ret) { + error_report("%s hook returned %d", __func__, ret); + } + return ret; +} + +/** + * smmu_page_walk_level_64 - Walk an IOVA range from a specific level + * @baseaddr: table base address corresponding to @level + * @level: level + * @cfg: translation config + * @start: end of the IOVA range + * @end: end of the IOVA range + * @hook_fn: the hook that to be called for each detected area + * @private: private data for the hook function + * @flags: access flags of the parent + * @nofail: indicates whether each iova of the range + * must be translated or whether failure is allowed + * + * Return 0 on success, < 0 on errors not related to translation + * process, > 1 on errors related to translation process (only + * if nofail is set) + */ +static int +smmu_page_walk_level_64(dma_addr_t baseaddr, int level, + SMMUTransCfg *cfg, uint64_t start, uint64_t end, + smmu_page_walk_hook hook_fn, void *private, + IOMMUAccessFlags flags, bool nofail) +{ + uint64_t subpage_size, subpage_mask, pte, iova =3D start; + int ret, granule_sz, stage, perm; + + granule_sz =3D cfg->granule_sz; + stage =3D cfg->stage; + subpage_size =3D 1ULL << level_shift(level, granule_sz); + subpage_mask =3D level_page_mask(level, granule_sz); + + trace_smmu_page_walk_level_in(level, baseaddr, granule_sz, + start, end, flags, subpage_size); + + while (iova < end) { + dma_addr_t next_table_baseaddr; + uint64_t iova_next, pte_addr; + uint32_t offset; + + iova_next =3D (iova & subpage_mask) + subpage_size; + offset =3D iova_level_offset(iova, level, granule_sz); + pte_addr =3D baseaddr + offset * sizeof(pte); + pte =3D get_pte(baseaddr, offset); + + trace_smmu_page_walk_level(level, iova, subpage_size, + baseaddr, offset, pte); + + if (pte =3D=3D (uint64_t)-1) { + if (nofail) { + return SMMU_TRANS_ERR_WALK_EXT_ABRT; + } + goto next; + } + if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) { + trace_smmu_page_walk_level_res_invalid_pte(stage, level, basea= ddr, + pte_addr, offset, p= te); + if (nofail) { + return SMMU_TRANS_ERR_TRANS; + } + goto next; + } + + if (is_page_pte(pte, level)) { + uint64_t gpa =3D get_page_pte_address(pte, granule_sz); + + perm =3D flags & pte_ap_to_perm(pte, true); + + trace_smmu_page_walk_level_page_pte(stage, level, iova, + baseaddr, pte_addr, pte, g= pa); + ret =3D call_entry_hook(iova, subpage_mask, gpa, perm, + hook_fn, private); + if (ret) { + return ret; + } + goto next; + } + if (is_block_pte(pte, level)) { + size_t target_page_size =3D qemu_target_page_size();; + uint64_t block_size, top_iova; + hwaddr gpa, block_gpa; + + block_gpa =3D get_block_pte_address(pte, level, granule_sz, + &block_size); + perm =3D flags & pte_ap_to_perm(pte, true); + + if (block_gpa =3D=3D -1) { + if (nofail) { + return SMMU_TRANS_ERR_WALK_EXT_ABRT; + } else { + goto next; + } + } + trace_smmu_page_walk_level_block_pte(stage, level, baseaddr, + pte_addr, pte, iova, bloc= k_gpa, + (int)(block_size >> 20)); + + gpa =3D block_gpa + (iova & (block_size - 1)); + if ((block_gpa =3D=3D gpa) && (end >=3D iova_next - 1)) { + ret =3D call_entry_hook(iova, ~(block_size - 1), block_gpa, + perm, hook_fn, private); + if (ret) { + return ret; + } + goto next; + } else { + top_iova =3D MIN(end, iova_next); + while (iova < top_iova) { + gpa =3D block_gpa + (iova & (block_size - 1)); + ret =3D call_entry_hook(iova, ~(target_page_size - 1), + gpa, perm, hook_fn, private); + if (ret) { + return ret; + } + iova +=3D target_page_size; + } + } + } + if (level =3D=3D 3) { + goto next; + } + /* table pte */ + next_table_baseaddr =3D get_table_pte_address(pte, granule_sz); + trace_smmu_page_walk_level_table_pte(stage, level, baseaddr, pte_a= ddr, + pte, next_table_baseaddr); + perm =3D flags & pte_ap_to_perm(pte, false); + ret =3D smmu_page_walk_level_64(next_table_baseaddr, level + 1, cf= g, + iova, MIN(iova_next, end), + hook_fn, private, perm, nofail); + if (ret) { + return ret; + } + +next: + iova =3D iova_next; + } + + return SMMU_TRANS_ERR_NONE; +} + +/** + * smmu_page_walk - walk a specific IOVA range from the initial + * lookup level, and call the hook for each valid entry + * + * @cfg: translation config + * @start: start of the IOVA range + * @end: end of the IOVA range + * @nofail: if true, each IOVA within the range must have a translation + * @hook_fn: the hook that to be called for each detected area + * @private: private data for the hook function + */ +int smmu_page_walk(SMMUTransCfg *cfg, uint64_t start, uint64_t end, + bool nofail, smmu_page_walk_hook hook_fn, void *private) +{ + uint64_t roof =3D MIN(end, (1ULL << (64 - cfg->tsz)) - 1); + IOMMUAccessFlags perm =3D IOMMU_ACCESS_FLAG(true, true); + int stage =3D cfg->stage; + dma_addr_t ttbr; + + if (!hook_fn) { + return 0; + } + + if (!cfg->aa64) { + error_report("VMSAv8-32 page walk is not yet implemented"); + abort(); + } + + ttbr =3D extract64(cfg->ttbr, 0, 48); + trace_smmu_page_walk(stage, cfg->ttbr, cfg->initial_level, start, roof= ); + + return smmu_page_walk_level_64(ttbr, cfg->initial_level, cfg, start, r= oof, + hook_fn, private, perm, nofail); +} + +/** + * set_translated_address: page table walk callback for smmu_translate + * + * once a leaf entry is found, applies the offset to the translated address + * and check the permission + * + * @entry: entry filled by the page table walk function, ie. contains the + * leaf entry iova/translated addr and permission flags + * @private: pointer to the original entry that must be translated + */ +static int set_translated_address(IOMMUTLBEntry *entry, void *private) +{ + IOMMUTLBEntry *tlbe_in =3D (IOMMUTLBEntry *)private; + size_t offset =3D tlbe_in->iova - entry->iova; + + if (((tlbe_in->perm & IOMMU_RO) && !(entry->perm & IOMMU_RO)) || + ((tlbe_in->perm & IOMMU_WO) && !(entry->perm & IOMMU_WO))) { + return SMMU_TRANS_ERR_PERM; + } + tlbe_in->translated_addr =3D entry->translated_addr + offset; + trace_smmu_set_translated_address(tlbe_in->iova, tlbe_in->translated_a= ddr); + return 0; +} + +/** + * smmu_translate - Attempt to translate a given entry according to @cfg + * + * @cfg: translation configuration + * @tlbe: entry pre-filled with the input iova, mask + * + * return: !=3D0 if no mapping is found for the tlbe->iova or access permi= ssion + * does not match + */ +int smmu_translate(SMMUTransCfg *cfg, IOMMUTLBEntry *tlbe) +{ + int ret =3D 0; + + if (cfg->bypassed || cfg->disabled) { + return 0; + } + + ret =3D smmu_page_walk(cfg, tlbe->iova, tlbe->iova + 1, true /* nofail= */, + set_translated_address, tlbe); + + if (ret) { + error_report("translation failed for iova=3D0x%"PRIx64" perm=3D%d = (%d)", + tlbe->iova, tlbe->perm, ret); + goto exit; + } + +exit: + return ret; +} =20 inline MemTxResult smmu_read_sysmem(dma_addr_t addr, void *buf, dma_addr_t= len, bool secure) diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h new file mode 100644 index 0000000..aeeadd4 --- /dev/null +++ b/hw/arm/smmu-internal.h @@ -0,0 +1,105 @@ +/* + * ARM SMMU support - Internal API + * + * Copyright (c) 2017 Red Hat, Inc. + * Written by Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMU_INTERNAL_H +#define HW_ARM_SMMU_INTERNAL_H + +#define ARM_LPAE_MAX_ADDR_BITS 48 +#define ARM_LPAE_MAX_LEVELS 4 + +/* PTE Manipulation */ + +#define ARM_LPAE_PTE_TYPE_SHIFT 0 +#define ARM_LPAE_PTE_TYPE_MASK 0x3 + +#define ARM_LPAE_PTE_TYPE_BLOCK 1 +#define ARM_LPAE_PTE_TYPE_RESERVED 1 +#define ARM_LPAE_PTE_TYPE_TABLE 3 +#define ARM_LPAE_PTE_TYPE_PAGE 3 + +#define ARM_LPAE_PTE_VALID (1 << 0) + +static inline bool is_invalid_pte(uint64_t pte) +{ + return !(pte & ARM_LPAE_PTE_VALID); +} + +static inline bool is_reserved_pte(uint64_t pte, int level) +{ + return ((level =3D=3D 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_RESER= VED)); +} + +static inline bool is_block_pte(uint64_t pte, int level) +{ + return ((level < 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_BLOCK= )); +} + +static inline bool is_table_pte(uint64_t pte, int level) +{ + return ((level < 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_TABLE= )); +} + +static inline bool is_page_pte(uint64_t pte, int level) +{ + return ((level =3D=3D 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_PAGE)= ); +} + +static IOMMUAccessFlags pte_ap_to_perm(uint64_t pte, bool is_leaf) +{ + int ap; + IOMMUAccessFlags flags; + + if (is_leaf) { + ap =3D extract64(pte, 6, 2); + } else { + ap =3D extract64(pte, 61, 2); + } + flags =3D IOMMU_ACCESS_FLAG(true, !(ap & 0x2)); + return flags; +} + +/* Level Indexing */ + +static inline int level_shift(int level, int granule_sz) +{ + return granule_sz + (3 - level) * (granule_sz - 3); +} + +static inline uint64_t level_page_mask(int level, int granule_sz) +{ + return ~((1ULL << level_shift(level, granule_sz)) - 1); +} + +/** + * TODO: handle the case where the level resolves less than + * granule_sz -3 IA bits. + */ +static inline +uint64_t iova_level_offset(uint64_t iova, int level, int granule_sz) +{ + return (iova >> level_shift(level, granule_sz)) & + ((1ULL << (granule_sz - 3)) - 1); +} + +#endif diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 193063e..c67cd39 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -2,3 +2,15 @@ =20 # hw/arm/virt-acpi-build.c virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out." + +# hw/arm/smmu-common.c + +smmu_page_walk(int stage, uint64_t baseaddr, int first_level, uint64_t sta= rt, uint64_t end) "stage=3D%d, baseaddr=3D0x%"PRIx64", first level=3D%d, st= art=3D0x%"PRIx64", end=3D0x%"PRIx64 +smmu_page_walk_level_in(int level, uint64_t baseaddr, int granule_sz, uint= 64_t start, uint64_t end, int flags, uint64_t subpage_size) "level=3D%d bas= eaddr=3D0x%"PRIx64" granule=3D%d, start=3D0x%"PRIx64" end=3D0x%"PRIx64" fla= gs=3D%d subpage_size=3D0x%lx" +smmu_page_walk_level(int level, uint64_t iova, size_t subpage_size, uint64= _t baseaddr, uint32_t offset, uint64_t pte) "level=3D%d iova=3D0x%lx subpag= e_sz=3D0x%lx baseaddr=3D0x%"PRIx64" offset=3D%d =3D> pte=3D0x%lx" +smmu_page_walk_level_res_invalid_pte(int stage, int level, uint64_t basead= dr, uint64_t pteaddr, uint32_t offset, uint64_t pte) "stage=3D%d level=3D%d= base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" offset=3D%d pte=3D0x%lx" +smmu_page_walk_level_page_pte(int stage, int level, uint64_t iova, uint64= _t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d = level=3D%d iova=3D0x%"PRIx64" base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D= 0x%"PRIx64" page address =3D 0x%"PRIx64 +smmu_page_walk_level_block_pte(int stage, int level, uint64_t baseaddr, ui= nt64_t pteaddr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "s= tage=3D%d level=3D%d base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx6= 4" iova=3D0x%"PRIx64" block address =3D 0x%"PRIx64" block size =3D %d MiB" +smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, ui= nt64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d, level=3D%d bas= e@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" next table address = =3D 0x%"PRIx64 +smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte)= "baseaddr=3D0x%"PRIx64" index=3D0x%x, pteaddr=3D0x%"PRIx64", pte=3D0x%"PRI= x64 +smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova =3D 0x%"PRIx64" = -> pa =3D 0x%"PRIx64 diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index a5999b0..112a11c 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -116,4 +116,8 @@ MemTxResult smmu_read_sysmem(dma_addr_t addr, void *buf, dma_addr_t len, bool secure); void smmu_write_sysmem(dma_addr_t addr, void *buf, dma_addr_t len, bool se= cure); =20 +int smmu_translate(SMMUTransCfg *cfg, IOMMUTLBEntry *tlbe); +int smmu_page_walk(SMMUTransCfg *cfg, uint64_t start, uint64_t end, + bool nofail, smmu_page_walk_hook hook_fn, void *private= ); + #endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 150428680285947.65926872830414; Fri, 1 Sep 2017 10:26:42 -0700 (PDT) Received: from localhost ([::1]:51276 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpiL-00009G-JJ for importer@patchew.org; Fri, 01 Sep 2017 13:26:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36570) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpeO-0005Gr-1l for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpeL-0002bb-BJ for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54760) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpeB-0002S5-T9; Fri, 01 Sep 2017 13:22:24 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AE993883D2; Fri, 1 Sep 2017 17:22:22 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id E214D52FA0; Fri, 1 Sep 2017 17:22:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com AE993883D2 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:08 +0200 Message-Id: <1504286483-23327-6-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 01 Sep 2017 17:22:23 +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] [PATCH v7 05/20] hw/arm/smmuv3: Skeleton 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, wtownsen@redhat.com 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" From: Prem Mallappa This patch implements a skeleton for the smmuv3 device. Datatypes and register definitions are introduced. The MMIO region, the interrupts and the queue are initialized (PRI is not supported). Only the MMIO read operation is implemented here. Signed-off-by: Prem Mallappa Signed-off-by: Eric Auger --- v6 -> v7: - split into several patches v5 -> v6: - Use IOMMUMemoryregion - regs become uint32_t and fix 64b MMIO access (.impl) - trace_smmuv3_write/read_mmio take the size param v4 -> v5: - change smmuv3_translate proto (IOMMUAccessFlags flag) - has_stagex replaced by is_ste_stagex - smmu_cfg_populate removed - added smmuv3_decode_config and reworked error management - remwork the naming of IOMMU mrs - fix SMMU_CMDQ_CONS offset v3 -> v4 - smmu_irq_update - fix hash key allocation - set smmu_iommu_ops - set SMMU_REG_CR0, - smmuv3_translate: ret.perm not set in bypass mode - use trace events - renamed STM2U64 into L1STD_L2PTR and STMSPAN into L1STD_SPAN - rework smmu_find_ste - fix tg2granule in TT0/0b10 corresponds to 16kB v2 -> v3: - move creation of include/hw/arm/smmuv3.h to this patch to fix compil issue - compilation allowed - fix sbus allocation in smmu_init_pci_iommu - restructure code into headers - misc cleanups --- hw/arm/Makefile.objs | 2 +- hw/arm/smmuv3-internal.h | 201 +++++++++++++++++++++++++++++++++++++++ hw/arm/smmuv3.c | 239 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 3 + include/hw/arm/smmuv3.h | 79 ++++++++++++++++ 5 files changed, 523 insertions(+), 1 deletion(-) create mode 100644 hw/arm/smmuv3-internal.h create mode 100644 hw/arm/smmuv3.c create mode 100644 include/hw/arm/smmuv3.h diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 5b2d38d..a7c808b 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -19,4 +19,4 @@ obj-$(CONFIG_FSL_IMX31) +=3D fsl-imx31.o kzm.o obj-$(CONFIG_FSL_IMX6) +=3D fsl-imx6.o sabrelite.o obj-$(CONFIG_ASPEED_SOC) +=3D aspeed_soc.o aspeed.o obj-$(CONFIG_MPS2) +=3D mps2.o -obj-$(CONFIG_ARM_SMMUV3) +=3D smmu-common.o +obj-$(CONFIG_ARM_SMMUV3) +=3D smmu-common.o smmuv3.o diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h new file mode 100644 index 0000000..488acc8 --- /dev/null +++ b/hw/arm/smmuv3-internal.h @@ -0,0 +1,201 @@ +/* + * ARM SMMUv3 support - Internal API + * + * Copyright (C) 2014-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMU_V3_INTERNAL_H +#define HW_ARM_SMMU_V3_INTERNAL_H + +#include "trace.h" +#include "qemu/error-report.h" +#include "hw/arm/smmu-common.h" + +/***************************** + * MMIO Register + *****************************/ +enum { + SMMU_REG_IDR0 =3D 0x0, + +/* IDR0 Field Values and supported features */ + +#define SMMU_IDR0_S2P 1 /* stage 2 */ +#define SMMU_IDR0_S1P 1 /* stage 1 */ +#define SMMU_IDR0_TTF 2 /* Aarch64 only - not Aarch32 (LPAE) */ +#define SMMU_IDR0_COHACC 1 /* IO coherent access */ +#define SMMU_IDR0_HTTU 2 /* Access and Dirty flag update */ +#define SMMU_IDR0_HYP 0 /* Hypervisor Stage 1 contexts */ +#define SMMU_IDR0_ATS 0 /* PCIe RC ATS */ +#define SMMU_IDR0_ASID16 1 /* 16-bit ASID */ +#define SMMU_IDR0_PRI 0 /* Page Request Interface */ +#define SMMU_IDR0_VMID16 0 /* 16-bit VMID */ +#define SMMU_IDR0_CD2L 0 /* 2-level Context Descriptor table */ +#define SMMU_IDR0_STALL 1 /* Stalling fault model */ +#define SMMU_IDR0_TERM 1 /* Termination model behaviour */ +#define SMMU_IDR0_STLEVEL 1 /* Multi-level Stream Table */ + +#define SMMU_IDR0_S2P_SHIFT 0 +#define SMMU_IDR0_S1P_SHIFT 1 +#define SMMU_IDR0_TTF_SHIFT 2 +#define SMMU_IDR0_COHACC_SHIFT 4 +#define SMMU_IDR0_HTTU_SHIFT 6 +#define SMMU_IDR0_HYP_SHIFT 9 +#define SMMU_IDR0_ATS_SHIFT 10 +#define SMMU_IDR0_ASID16_SHIFT 12 +#define SMMU_IDR0_PRI_SHIFT 16 +#define SMMU_IDR0_VMID16_SHIFT 18 +#define SMMU_IDR0_CD2L_SHIFT 19 +#define SMMU_IDR0_STALL_SHIFT 24 +#define SMMU_IDR0_TERM_SHIFT 26 +#define SMMU_IDR0_STLEVEL_SHIFT 27 + + SMMU_REG_IDR1 =3D 0x4, +#define SMMU_IDR1_SIDSIZE 16 + SMMU_REG_IDR2 =3D 0x8, + SMMU_REG_IDR3 =3D 0xc, + SMMU_REG_IDR4 =3D 0x10, + SMMU_REG_IDR5 =3D 0x14, +#define SMMU_IDR5_GRAN_SHIFT 4 +#define SMMU_IDR5_GRAN 0b101 /* GRAN4K, GRAN64K */ +#define SMMU_IDR5_OAS 4 /* 44 bits */ + SMMU_REG_IIDR =3D 0x1c, + SMMU_REG_CR0 =3D 0x20, + +#define SMMU_CR0_SMMU_ENABLE (1 << 0) +#define SMMU_CR0_PRIQ_ENABLE (1 << 1) +#define SMMU_CR0_EVTQ_ENABLE (1 << 2) +#define SMMU_CR0_CMDQ_ENABLE (1 << 3) +#define SMMU_CR0_ATS_CHECK (1 << 4) + + SMMU_REG_CR0_ACK =3D 0x24, + SMMU_REG_CR1 =3D 0x28, + SMMU_REG_CR2 =3D 0x2c, + + SMMU_REG_STATUSR =3D 0x40, + + SMMU_REG_IRQ_CTRL =3D 0x50, + SMMU_REG_IRQ_CTRL_ACK =3D 0x54, + +#define SMMU_IRQ_CTRL_GERROR_EN (1 << 0) +#define SMMU_IRQ_CTRL_EVENT_EN (1 << 1) +#define SMMU_IRQ_CTRL_PRI_EN (1 << 2) + + SMMU_REG_GERROR =3D 0x60, + +#define SMMU_GERROR_CMDQ (1 << 0) +#define SMMU_GERROR_EVENTQ_ABT (1 << 2) +#define SMMU_GERROR_PRIQ_ABT (1 << 3) +#define SMMU_GERROR_MSI_CMDQ_ABT (1 << 4) +#define SMMU_GERROR_MSI_EVENTQ_ABT (1 << 5) +#define SMMU_GERROR_MSI_PRIQ_ABT (1 << 6) +#define SMMU_GERROR_MSI_GERROR_ABT (1 << 7) +#define SMMU_GERROR_SFM_ERR (1 << 8) + + SMMU_REG_GERRORN =3D 0x64, + SMMU_REG_GERROR_IRQ_CFG0 =3D 0x68, + SMMU_REG_GERROR_IRQ_CFG1 =3D 0x70, + SMMU_REG_GERROR_IRQ_CFG2 =3D 0x74, + + /* SMMU_BASE_RA Applies to STRTAB_BASE, CMDQ_BASE and EVTQ_BASE */ +#define SMMU_BASE_RA (1ULL << 62) + SMMU_REG_STRTAB_BASE =3D 0x80, + SMMU_REG_STRTAB_BASE_CFG =3D 0x88, + + SMMU_REG_CMDQ_BASE =3D 0x90, + SMMU_REG_CMDQ_PROD =3D 0x98, + SMMU_REG_CMDQ_CONS =3D 0x9c, + /* CMD Consumer (CONS) */ +#define SMMU_CMD_CONS_ERR_SHIFT 24 +#define SMMU_CMD_CONS_ERR_BITS 7 + + SMMU_REG_EVTQ_BASE =3D 0xa0, + SMMU_REG_EVTQ_PROD =3D 0xa8, + SMMU_REG_EVTQ_CONS =3D 0xac, + SMMU_REG_EVTQ_IRQ_CFG0 =3D 0xb0, + SMMU_REG_EVTQ_IRQ_CFG1 =3D 0xb8, + SMMU_REG_EVTQ_IRQ_CFG2 =3D 0xbc, + + SMMU_REG_PRIQ_BASE =3D 0xc0, + SMMU_REG_PRIQ_PROD =3D 0xc8, + SMMU_REG_PRIQ_CONS =3D 0xcc, + SMMU_REG_PRIQ_IRQ_CFG0 =3D 0xd0, + SMMU_REG_PRIQ_IRQ_CFG1 =3D 0xd8, + SMMU_REG_PRIQ_IRQ_CFG2 =3D 0xdc, + + SMMU_ID_REGS_OFFSET =3D 0xfd0, + + /* Secure registers are not used for now */ + SMMU_SECURE_OFFSET =3D 0x8000, +}; + +/********************** + * Data Structures + **********************/ + +struct __smmu_data2 { + uint32_t word[2]; +}; + +struct __smmu_data8 { + uint32_t word[8]; +}; + +struct __smmu_data16 { + uint32_t word[16]; +}; + +struct __smmu_data4 { + uint32_t word[4]; +}; + +typedef struct __smmu_data4 Cmd; /* Command Entry */ +typedef struct __smmu_data8 Evt; /* Event Entry */ + +/***************************** + * Register Access Primitives + *****************************/ + +static inline void smmu_write32_reg(SMMUV3State *s, uint32_t addr, uint32_= t val) +{ + s->regs[addr >> 2] =3D val; +} + +static inline void smmu_write64_reg(SMMUV3State *s, uint32_t addr, uint64_= t val) +{ + addr >>=3D 2; + s->regs[addr] =3D extract64(val, 0, 32); + s->regs[addr + 1] =3D extract64(val, 32, 32); +} + +static inline uint32_t smmu_read32_reg(SMMUV3State *s, uint32_t addr) +{ + return s->regs[addr >> 2]; +} + +static inline uint64_t smmu_read64_reg(SMMUV3State *s, uint32_t addr) +{ + addr >>=3D 2; + return s->regs[addr] | ((uint64_t)(s->regs[addr + 1]) << 32); +} + +static inline int smmu_enabled(SMMUV3State *s) +{ + return smmu_read32_reg(s, SMMU_REG_CR0) & SMMU_CR0_SMMU_ENABLE; +} + +#endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c new file mode 100644 index 0000000..0a7cd1c --- /dev/null +++ b/hw/arm/smmuv3.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2014-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "exec/address-spaces.h" +#include "trace.h" +#include "qemu/error-report.h" + +#include "hw/arm/smmuv3.h" +#include "smmuv3-internal.h" + +static void smmuv3_init_regs(SMMUV3State *s) +{ + uint32_t data =3D + SMMU_IDR0_STLEVEL << SMMU_IDR0_STLEVEL_SHIFT | + SMMU_IDR0_TERM << SMMU_IDR0_TERM_SHIFT | + SMMU_IDR0_STALL << SMMU_IDR0_STALL_SHIFT | + SMMU_IDR0_VMID16 << SMMU_IDR0_VMID16_SHIFT | + SMMU_IDR0_PRI << SMMU_IDR0_PRI_SHIFT | + SMMU_IDR0_ASID16 << SMMU_IDR0_ASID16_SHIFT | + SMMU_IDR0_ATS << SMMU_IDR0_ATS_SHIFT | + SMMU_IDR0_HYP << SMMU_IDR0_HYP_SHIFT | + SMMU_IDR0_HTTU << SMMU_IDR0_HTTU_SHIFT | + SMMU_IDR0_COHACC << SMMU_IDR0_COHACC_SHIFT | + SMMU_IDR0_TTF << SMMU_IDR0_TTF_SHIFT | + SMMU_IDR0_S1P << SMMU_IDR0_S1P_SHIFT | + SMMU_IDR0_S2P << SMMU_IDR0_S2P_SHIFT; + + smmu_write32_reg(s, SMMU_REG_IDR0, data); + +#define SMMU_QUEUE_SIZE_LOG2 19 + data =3D + 1 << 27 | /* Attr Types override */ + SMMU_QUEUE_SIZE_LOG2 << 21 | /* Cmd Q size */ + SMMU_QUEUE_SIZE_LOG2 << 16 | /* Event Q size */ + SMMU_QUEUE_SIZE_LOG2 << 11 | /* PRI Q size */ + 0 << 6 | /* SSID not supported */ + SMMU_IDR1_SIDSIZE; + + smmu_write32_reg(s, SMMU_REG_IDR1, data); + + s->sid_size =3D SMMU_IDR1_SIDSIZE; + + data =3D SMMU_IDR5_GRAN << SMMU_IDR5_GRAN_SHIFT | SMMU_IDR5_OAS; + + smmu_write32_reg(s, SMMU_REG_IDR5, data); +} + +static void smmuv3_init_queues(SMMUV3State *s) +{ + s->cmdq.prod =3D 0; + s->cmdq.cons =3D 0; + s->cmdq.wrap.prod =3D 0; + s->cmdq.wrap.cons =3D 0; + + s->evtq.prod =3D 0; + s->evtq.cons =3D 0; + s->evtq.wrap.prod =3D 0; + s->evtq.wrap.cons =3D 0; + + s->cmdq.entries =3D SMMU_QUEUE_SIZE_LOG2; + s->cmdq.ent_size =3D sizeof(Cmd); + s->evtq.entries =3D SMMU_QUEUE_SIZE_LOG2; + s->evtq.ent_size =3D sizeof(Evt); +} + +static void smmuv3_init(SMMUV3State *s) +{ + smmuv3_init_regs(s); + smmuv3_init_queues(s); +} + +static inline void smmu_update_base_reg(SMMUV3State *s, uint64_t *base, + uint64_t val) +{ + *base =3D val & ~(SMMU_BASE_RA | 0x3fULL); +} + +static void smmu_write_mmio_fixup(SMMUV3State *s, hwaddr *addr) +{ + switch (*addr) { + case 0x100a8: case 0x100ac: /* Aliasing =3D> page0 registers */ + case 0x100c8: case 0x100cc: + *addr ^=3D (hwaddr)0x10000; + } +} + +static void smmu_write_mmio(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ +} + +static uint64_t smmu_read_mmio(void *opaque, hwaddr addr, unsigned size) +{ + SMMUState *sys =3D opaque; + SMMUV3State *s =3D SMMU_V3_DEV(sys); + uint64_t val; + + smmu_write_mmio_fixup(s, &addr); + + /* Primecell/Corelink ID registers */ + switch (addr) { + case 0xFF0 ... 0xFFC: + case 0xFDC ... 0xFE4: + val =3D 0; + error_report("addr:0x%"PRIx64" val:0x%"PRIx64, addr, val); + break; + case SMMU_REG_STRTAB_BASE ... SMMU_REG_CMDQ_BASE: + case SMMU_REG_EVTQ_BASE: + case SMMU_REG_PRIQ_BASE ... SMMU_REG_PRIQ_IRQ_CFG1: + val =3D smmu_read64_reg(s, addr); + break; + default: + val =3D (uint64_t)smmu_read32_reg(s, addr); + break; + } + + trace_smmuv3_read_mmio(addr, val, size); + return val; +} + +static const MemoryRegionOps smmu_mem_ops =3D { + .read =3D smmu_read_mmio, + .write =3D smmu_write_mmio, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, + .impl =3D { + .min_access_size =3D 4, + .max_access_size =3D 8, + }, +}; + +static void smmu_init_irq(SMMUV3State *s, SysBusDevice *dev) +{ + int i; + + for (i =3D 0; i < ARRAY_SIZE(s->irq); i++) { + sysbus_init_irq(dev, &s->irq[i]); + } +} + +static void smmu_reset(DeviceState *dev) +{ + SMMUV3State *s =3D SMMU_V3_DEV(dev); + smmuv3_init(s); +} + +static void smmu_realize(DeviceState *d, Error **errp) +{ + SMMUState *sys =3D SMMU_SYS_DEV(d); + SMMUV3State *s =3D SMMU_V3_DEV(sys); + SysBusDevice *dev =3D SYS_BUS_DEVICE(d); + + memory_region_init_io(&sys->iomem, OBJECT(s), + &smmu_mem_ops, sys, TYPE_SMMU_V3_DEV, 0x20000); + + sys->mrtypename =3D g_strdup(TYPE_SMMUV3_IOMMU_MEMORY_REGION); + + sysbus_init_mmio(dev, &sys->iomem); + + smmu_init_irq(s, dev); +} + +static const VMStateDescription vmstate_smmuv3 =3D { + .name =3D "smmuv3", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, SMMUV3State, SMMU_NREGS), + VMSTATE_END_OF_LIST(), + }, +}; + +static void smmuv3_instance_init(Object *obj) +{ + /* Nothing much to do here as of now */ +} + +static void smmuv3_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->reset =3D smmu_reset; + dc->vmsd =3D &vmstate_smmuv3; + dc->realize =3D smmu_realize; +} + +static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, + void *data) +{ +} + +static const TypeInfo smmuv3_type_info =3D { + .name =3D TYPE_SMMU_V3_DEV, + .parent =3D TYPE_SMMU_DEV_BASE, + .instance_size =3D sizeof(SMMUV3State), + .instance_init =3D smmuv3_instance_init, + .class_data =3D NULL, + .class_size =3D sizeof(SMMUV3Class), + .class_init =3D smmuv3_class_init, +}; + +static const TypeInfo smmuv3_iommu_memory_region_info =3D { + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .name =3D TYPE_SMMUV3_IOMMU_MEMORY_REGION, + .class_init =3D smmuv3_iommu_memory_region_class_init, +}; + +static void smmuv3_register_types(void) +{ + type_register(&smmuv3_type_info); + type_register(&smmuv3_iommu_memory_region_info); +} + +type_init(smmuv3_register_types) + diff --git a/hw/arm/trace-events b/hw/arm/trace-events index c67cd39..8affbf7 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -14,3 +14,6 @@ smmu_page_walk_level_block_pte(int stage, int level, uint= 64_t baseaddr, uint64_t smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, ui= nt64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d, level=3D%d bas= e@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" next table address = =3D 0x%"PRIx64 smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte)= "baseaddr=3D0x%"PRIx64" index=3D0x%x, pteaddr=3D0x%"PRIx64", pte=3D0x%"PRI= x64 smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova =3D 0x%"PRIx64" = -> pa =3D 0x%"PRIx64 + +#hw/arm/smmuv3.c +smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx= 64" val:0x%"PRIx64" size: 0x%x" diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h new file mode 100644 index 0000000..0c8973d --- /dev/null +++ b/include/hw/arm/smmuv3.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMUV3_H +#define HW_ARM_SMMUV3_H + +#include "hw/arm/smmu-common.h" + +#define TYPE_SMMUV3_IOMMU_MEMORY_REGION "smmuv3-iommu-memory-region" + +#define SMMU_NREGS 0x200 + +typedef struct SMMUQueue { + hwaddr base; + uint32_t prod; + uint32_t cons; + union { + struct { + uint8_t prod:1; + uint8_t cons:1; + }; + uint8_t unused; + } wrap; + + uint16_t entries; /* Number of entries */ + uint8_t ent_size; /* Size of entry in bytes */ + uint8_t shift; /* Size in log2 */ +} SMMUQueue; + +typedef struct SMMUV3State { + SMMUState smmu_state; + + /* Local cache of most-frequently used registers */ +#define SMMU_FEATURE_2LVL_STE (1 << 0) + uint32_t features; + uint16_t sid_size; + uint16_t sid_split; + uint64_t strtab_base; + + uint32_t regs[SMMU_NREGS]; + + qemu_irq irq[4]; + SMMUQueue cmdq, evtq; + +} SMMUV3State; + +typedef enum { + SMMU_IRQ_EVTQ, + SMMU_IRQ_PRIQ, + SMMU_IRQ_CMD_SYNC, + SMMU_IRQ_GERROR, +} SMMUIrq; + +typedef struct { + SMMUBaseClass smmu_base_class; +} SMMUV3Class; + +#define TYPE_SMMU_V3_DEV "smmuv3" +#define SMMU_V3_DEV(obj) OBJECT_CHECK(SMMUV3State, (obj), TYPE_SMMU_V3_DEV) +#define SMMU_V3_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_SMMU_V3_DEV) + +#endif --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 150428697398354.68421462946651; Fri, 1 Sep 2017 10:29:33 -0700 (PDT) Received: from localhost ([::1]:51307 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpl7-0002tK-23 for importer@patchew.org; Fri, 01 Sep 2017 13:29:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36580) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpeP-0005Ht-9J for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpeK-0002aS-B1 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49608) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpeH-0002XL-Gn; Fri, 01 Sep 2017 13:22:29 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7BA7981DF5; Fri, 1 Sep 2017 17:22:28 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 16A2617100; Fri, 1 Sep 2017 17:22:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 7BA7981DF5 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:09 +0200 Message-Id: <1504286483-23327-7-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 01 Sep 2017 17:22:28 +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] [PATCH v7 06/20] hw/arm/smmuv3: Wired IRQ and GERROR helpers 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, wtownsen@redhat.com 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" We introduce some helpers to handle wired IRQs and especially GERROR interrupt. SMMU writes GERROR register on GERROR event and SW acks GERROR interrupts by setting GERRORn. The Wired interrupts are edge sensitive. Signed-off-by: Eric Auger --- Is CMD_SYNC interrupt enabled somewhere? --- hw/arm/smmuv3-internal.h | 20 ++++++++++++++++++ hw/arm/smmuv3.c | 55 ++++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 2 ++ 3 files changed, 77 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 488acc8..2b44ee2 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -198,4 +198,24 @@ static inline int smmu_enabled(SMMUV3State *s) return smmu_read32_reg(s, SMMU_REG_CR0) & SMMU_CR0_SMMU_ENABLE; } =20 +/***************************** + * Interrupts + *****************************/ + +#define smmu_evt_irq_enabled(s) \ + (smmu_read64_reg(s, SMMU_REG_IRQ_CTRL) & SMMU_IRQ_CTRL_EVENT_EN) +#define smmu_gerror_irq_enabled(s) \ + (smmu_read64_reg(s, SMMU_REG_IRQ_CTRL) & SMMU_IRQ_CTRL_GERROR_EN) +#define smmu_pri_irq_enabled(s) \ + (smmu_read64_reg(s, SMMU_REG_IRQ_CTRL) & SMMU_IRQ_CTRL_PRI_EN) + +#define SMMU_PENDING_GERRORS(s) \ + (smmu_read32_reg(s, SMMU_REG_GERROR) ^ \ + smmu_read32_reg(s, SMMU_REG_GERRORN)) + +#define SMMU_CMDQ_ERR(s) (SMMU_PENDING_GERRORS(s) & SMMU_GERROR_CMDQ) + +void smmuv3_irq_trigger(SMMUV3State *s, SMMUIrq irq, uint32_t gerror_val); +void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerrorn); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 0a7cd1c..468134f 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -29,6 +29,61 @@ #include "hw/arm/smmuv3.h" #include "smmuv3-internal.h" =20 +/** + * smmuv3_irq_trigger - pulse @irq if enabled and update + * GERROR register in case of GERROR interrupt + * + * @irq: irq type + * @gerror: gerror new value, only relevant if @irq is GERROR + */ +void smmuv3_irq_trigger(SMMUV3State *s, SMMUIrq irq, uint32_t gerror_val) +{ + uint32_t pending_gerrors =3D SMMU_PENDING_GERRORS(s); + bool pulse =3D false; + + switch (irq) { + case SMMU_IRQ_EVTQ: + pulse =3D smmu_evt_irq_enabled(s); + break; + case SMMU_IRQ_PRIQ: + pulse =3D smmu_pri_irq_enabled(s); + break; + case SMMU_IRQ_CMD_SYNC: + pulse =3D true; + break; + case SMMU_IRQ_GERROR: + { + /* don't toggle an already pending error */ + bool new_gerrors =3D ~pending_gerrors & gerror_val; + uint32_t gerror =3D smmu_read32_reg(s, SMMU_REG_GERROR); + + smmu_write32_reg(s, SMMU_REG_GERROR, gerror | new_gerrors); + + /* pulse the GERROR irq only if all fields were acked */ + pulse =3D smmu_gerror_irq_enabled(s) && !pending_gerrors; + break; + } + } + if (pulse) { + trace_smmuv3_irq_trigger(irq, + smmu_read32_reg(s, SMMU_REG_GERROR), + SMMU_PENDING_GERRORS(s)); + qemu_irq_pulse(s->irq[irq]); + } +} + +void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerrorn) +{ + uint32_t pending_gerrors =3D SMMU_PENDING_GERRORS(s); + uint32_t sanitized; + + /* Make sure SW does not toggle irqs that are not active */ + sanitized =3D gerrorn & pending_gerrors; + + smmu_write32_reg(s, SMMU_REG_GERRORN, sanitized); + trace_smmuv3_write_gerrorn(gerrorn, sanitized, SMMU_PENDING_GERRORS(s)= ); +} + static void smmuv3_init_regs(SMMUV3State *s) { uint32_t data =3D diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 8affbf7..c1ce8eb 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -17,3 +17,5 @@ smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova= =3D 0x%"PRIx64" -> pa =3D =20 #hw/arm/smmuv3.c smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx= 64" val:0x%"PRIx64" size: 0x%x" +smmuv3_irq_trigger(int irq, uint32_t gerror, uint32_t pending) "irq=3D%d g= error=3D0x%x pending gerrors=3D0x%x" +smmuv3_write_gerrorn(uint32_t gerrorn, uint32_t sanitized, uint32_t pendin= g) "gerrorn=3D0x%x sanitized=3D0x%x pending=3D0x%x" --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504286964768920.4339751211775; Fri, 1 Sep 2017 10:29:24 -0700 (PDT) Received: from localhost ([::1]:51302 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpkx-0002gg-45 for importer@patchew.org; Fri, 01 Sep 2017 13:29:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36866) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpei-0005Yu-Qc for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnped-0002th-SK for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:22:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40824) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpeU-0002kw-Ik; Fri, 01 Sep 2017 13:22:42 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 95E3961980; Fri, 1 Sep 2017 17:22:41 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id D33A0627DE; Fri, 1 Sep 2017 17:22:28 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 95E3961980 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:10 +0200 Message-Id: <1504286483-23327-8-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 01 Sep 2017 17:22:41 +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] [PATCH v7 07/20] hw/arm/smmuv3: Queue helpers 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, wtownsen@redhat.com 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" We introduce helpers to read/write into the circular queues. smmuv3_read_cmdq and smmuv3_write_evtq will become static later on. Signed-off-by: Eric Auger --- hw/arm/smmuv3-internal.h | 48 ++++++++++++++++++++++++++++++- hw/arm/smmuv3.c | 75 ++++++++++++++++++++++++++++++++++++++++++++= +++- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 2b44ee2..d88f141 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -215,7 +215,53 @@ static inline int smmu_enabled(SMMUV3State *s) =20 #define SMMU_CMDQ_ERR(s) (SMMU_PENDING_GERRORS(s) & SMMU_GERROR_CMDQ) =20 -void smmuv3_irq_trigger(SMMUV3State *s, SMMUIrq irq, uint32_t gerror_val); void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerrorn); =20 +/*************************** + * Queue Handling + ***************************/ + +typedef enum { + CMD_Q_EMPTY, + CMD_Q_FULL, + CMD_Q_PARTIALLY_FILLED, +} SMMUQStatus; + +#define Q_ENTRY(q, idx) (q->base + q->ent_size * idx) +#define Q_WRAP(q, pc) ((pc) >> (q)->shift) +#define Q_IDX(q, pc) ((pc) & ((1 << (q)->shift) - 1)) + +static inline SMMUQStatus __smmu_queue_status(SMMUV3State *s, SMMUQueue *q) +{ + uint32_t prod =3D Q_IDX(q, q->prod); + uint32_t cons =3D Q_IDX(q, q->cons); + + if ((prod =3D=3D cons) && (q->wrap.prod !=3D q->wrap.cons)) { + return CMD_Q_FULL; + } else if ((prod =3D=3D cons) && (q->wrap.prod =3D=3D q->wrap.cons)) { + return CMD_Q_EMPTY; + } + return CMD_Q_PARTIALLY_FILLED; +} +#define smmu_is_q_full(s, q) (__smmu_queue_status(s, q) =3D=3D CMD_Q_FULL) +#define smmu_is_q_empty(s, q) (__smmu_queue_status(s, q) =3D=3D CMD_Q_EMPT= Y) + +static inline int __smmu_q_enabled(SMMUV3State *s, uint32_t q) +{ + return smmu_read32_reg(s, SMMU_REG_CR0) & q; +} +#define smmu_cmd_q_enabled(s) __smmu_q_enabled(s, SMMU_CR0_CMDQ_ENABLE) +#define smmu_evt_q_enabled(s) __smmu_q_enabled(s, SMMU_CR0_EVTQ_ENABLE) + +static inline void smmu_write_cmdq_err(SMMUV3State *s, uint32_t err_type) +{ + uint32_t regval =3D smmu_read32_reg(s, SMMU_REG_CMDQ_CONS); + + smmu_write32_reg(s, SMMU_REG_CMDQ_CONS, + regval | err_type << SMMU_CMD_CONS_ERR_SHIFT); +} + +MemTxResult smmuv3_read_cmdq(SMMUV3State *s, Cmd *cmd); +void smmuv3_write_evtq(SMMUV3State *s, Evt *evt); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 468134f..2f96463 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -36,7 +36,7 @@ * @irq: irq type * @gerror: gerror new value, only relevant if @irq is GERROR */ -void smmuv3_irq_trigger(SMMUV3State *s, SMMUIrq irq, uint32_t gerror_val) +static void smmuv3_irq_trigger(SMMUV3State *s, SMMUIrq irq, uint32_t gerro= r_val) { uint32_t pending_gerrors =3D SMMU_PENDING_GERRORS(s); bool pulse =3D false; @@ -84,6 +84,79 @@ void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerro= rn) trace_smmuv3_write_gerrorn(gerrorn, sanitized, SMMU_PENDING_GERRORS(s)= ); } =20 +static MemTxResult smmu_q_read(SMMUQueue *q, void *data) +{ + uint64_t addr =3D Q_ENTRY(q, Q_IDX(q, q->cons)); + MemTxResult ret; + + ret =3D smmu_read_sysmem(addr, data, q->ent_size, false); + if (ret !=3D MEMTX_OK) { + return ret; + } + + q->cons++; + if (q->cons =3D=3D q->entries) { + q->cons =3D 0; + q->wrap.cons++; + } + + return ret; +} + +static void smmu_q_write(SMMUQueue *q, void *data) +{ + uint64_t addr =3D Q_ENTRY(q, Q_IDX(q, q->prod)); + + smmu_write_sysmem(addr, data, q->ent_size, false); + + q->prod++; + if (q->prod =3D=3D q->entries) { + q->prod =3D 0; + q->wrap.prod++; + } +} + +MemTxResult smmuv3_read_cmdq(SMMUV3State *s, Cmd *cmd) +{ + SMMUQueue *q =3D &s->cmdq; + MemTxResult ret =3D smmu_q_read(q, cmd); + uint32_t val =3D 0; + + if (ret !=3D MEMTX_OK) { + return ret; + } + + val |=3D (q->wrap.cons << q->shift) | q->cons; + smmu_write32_reg(s, SMMU_REG_CMDQ_CONS, val); + + return ret; +} + +void smmuv3_write_evtq(SMMUV3State *s, Evt *evt) +{ + SMMUQueue *q =3D &s->evtq; + bool was_empty =3D smmu_is_q_empty(s, q); + bool was_full =3D smmu_is_q_full(s, q); + uint32_t val; + + if (!smmu_evt_q_enabled(s)) { + return; + } + + if (was_full) { + return; + } + + smmu_q_write(q, evt); + + val =3D (q->wrap.prod << q->shift) | q->prod; + smmu_write32_reg(s, SMMU_REG_EVTQ_PROD, val); + + if (was_empty) { + smmuv3_irq_trigger(s, SMMU_IRQ_EVTQ, 0); + } +} + static void smmuv3_init_regs(SMMUV3State *s) { uint32_t data =3D --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287017666598.0269032841568; Fri, 1 Sep 2017 10:30:17 -0700 (PDT) Received: from localhost ([::1]:51315 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnplo-0003hF-6J for importer@patchew.org; Fri, 01 Sep 2017 13:30:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:36923) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpem-0005bf-2x for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpeg-0002wE-1I for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53016) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpea-0002qI-At; Fri, 01 Sep 2017 13:22:48 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4C5307F7DA; Fri, 1 Sep 2017 17:22:47 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED6595450A; Fri, 1 Sep 2017 17:22:41 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 4C5307F7DA Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:11 +0200 Message-Id: <1504286483-23327-9-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Fri, 01 Sep 2017 17:22:47 +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] [PATCH v7 08/20] hw/arm/smmuv3: Implement MMIO write operations 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, wtownsen@redhat.com 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" Now we have relevant helpers for queue and irq management, let's implement MMIO write operations Signed-off-by: Eric Auger --- hw/arm/smmuv3-internal.h | 103 +++++++++++++++++++++++- hw/arm/smmuv3.c | 204 +++++++++++++++++++++++++++++++++++++++++++= +++- hw/arm/trace-events | 15 ++++ 3 files changed, 317 insertions(+), 5 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index d88f141..a5d60b4 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -215,8 +215,6 @@ static inline int smmu_enabled(SMMUV3State *s) =20 #define SMMU_CMDQ_ERR(s) (SMMU_PENDING_GERRORS(s) & SMMU_GERROR_CMDQ) =20 -void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerrorn); - /*************************** * Queue Handling ***************************/ @@ -261,7 +259,106 @@ static inline void smmu_write_cmdq_err(SMMUV3State *s= , uint32_t err_type) regval | err_type << SMMU_CMD_CONS_ERR_SHIFT); } =20 -MemTxResult smmuv3_read_cmdq(SMMUV3State *s, Cmd *cmd); void smmuv3_write_evtq(SMMUV3State *s, Evt *evt); =20 +/***************************** + * Commands + *****************************/ + +enum { + SMMU_CMD_PREFETCH_CONFIG =3D 0x01, + SMMU_CMD_PREFETCH_ADDR, + SMMU_CMD_CFGI_STE, + SMMU_CMD_CFGI_STE_RANGE, + SMMU_CMD_CFGI_CD, + SMMU_CMD_CFGI_CD_ALL, + SMMU_CMD_CFGI_ALL, + SMMU_CMD_TLBI_NH_ALL =3D 0x10, + SMMU_CMD_TLBI_NH_ASID, + SMMU_CMD_TLBI_NH_VA, + SMMU_CMD_TLBI_NH_VAA, + SMMU_CMD_TLBI_EL3_ALL =3D 0x18, + SMMU_CMD_TLBI_EL3_VA =3D 0x1a, + SMMU_CMD_TLBI_EL2_ALL =3D 0x20, + SMMU_CMD_TLBI_EL2_ASID, + SMMU_CMD_TLBI_EL2_VA, + SMMU_CMD_TLBI_EL2_VAA, /* 0x23 */ + SMMU_CMD_TLBI_S12_VMALL =3D 0x28, + SMMU_CMD_TLBI_S2_IPA =3D 0x2a, + SMMU_CMD_TLBI_NSNH_ALL =3D 0x30, + SMMU_CMD_ATC_INV =3D 0x40, + SMMU_CMD_PRI_RESP, + SMMU_CMD_RESUME =3D 0x44, + SMMU_CMD_STALL_TERM, + SMMU_CMD_SYNC, /* 0x46 */ +}; + +static const char *cmd_stringify[] =3D { + [SMMU_CMD_PREFETCH_CONFIG] =3D "SMMU_CMD_PREFETCH_CONFIG", + [SMMU_CMD_PREFETCH_ADDR] =3D "SMMU_CMD_PREFETCH_ADDR", + [SMMU_CMD_CFGI_STE] =3D "SMMU_CMD_CFGI_STE", + [SMMU_CMD_CFGI_STE_RANGE] =3D "SMMU_CMD_CFGI_STE_RANGE", + [SMMU_CMD_CFGI_CD] =3D "SMMU_CMD_CFGI_CD", + [SMMU_CMD_CFGI_CD_ALL] =3D "SMMU_CMD_CFGI_CD_ALL", + [SMMU_CMD_CFGI_ALL] =3D "SMMU_CMD_CFGI_ALL", + [SMMU_CMD_TLBI_NH_ALL] =3D "SMMU_CMD_TLBI_NH_ALL", + [SMMU_CMD_TLBI_NH_ASID] =3D "SMMU_CMD_TLBI_NH_ASID", + [SMMU_CMD_TLBI_NH_VA] =3D "SMMU_CMD_TLBI_NH_VA", + [SMMU_CMD_TLBI_NH_VAA] =3D "SMMU_CMD_TLBI_NH_VAA", + [SMMU_CMD_TLBI_EL3_ALL] =3D "SMMU_CMD_TLBI_EL3_ALL", + [SMMU_CMD_TLBI_EL3_VA] =3D "SMMU_CMD_TLBI_EL3_VA", + [SMMU_CMD_TLBI_EL2_ALL] =3D "SMMU_CMD_TLBI_EL2_ALL", + [SMMU_CMD_TLBI_EL2_ASID] =3D "SMMU_CMD_TLBI_EL2_ASID", + [SMMU_CMD_TLBI_EL2_VA] =3D "SMMU_CMD_TLBI_EL2_VA", + [SMMU_CMD_TLBI_EL2_VAA] =3D "SMMU_CMD_TLBI_EL2_VAA", + [SMMU_CMD_TLBI_S12_VMALL] =3D "SMMU_CMD_TLBI_S12_VMALL", + [SMMU_CMD_TLBI_S2_IPA] =3D "SMMU_CMD_TLBI_S2_IPA", + [SMMU_CMD_TLBI_NSNH_ALL] =3D "SMMU_CMD_TLBI_NSNH_ALL", + [SMMU_CMD_ATC_INV] =3D "SMMU_CMD_ATC_INV", + [SMMU_CMD_PRI_RESP] =3D "SMMU_CMD_PRI_RESP", + [SMMU_CMD_RESUME] =3D "SMMU_CMD_RESUME", + [SMMU_CMD_STALL_TERM] =3D "SMMU_CMD_STALL_TERM", + [SMMU_CMD_SYNC] =3D "SMMU_CMD_SYNC", +}; + +/***************************** + * CMDQ fields + *****************************/ + +typedef enum { + SMMU_CERROR_NONE =3D 0, + SMMU_CERROR_ILL, + SMMU_CERROR_ABT, + SMMU_CERROR_ATC_INV_SYNC, +} SMMUCmdError; + +enum { /* Command completion notification */ + CMD_SYNC_SIG_NONE, + CMD_SYNC_SIG_IRQ, + CMD_SYNC_SIG_SEV, +}; + +#define CMD_TYPE(x) extract32((x)->word[0], 0, 8) +#define CMD_SEC(x) extract32((x)->word[0], 9, 1) +#define CMD_SEV(x) extract32((x)->word[0], 10, 1) +#define CMD_AC(x) extract32((x)->word[0], 12, 1) +#define CMD_AB(x) extract32((x)->word[0], 13, 1) +#define CMD_CS(x) extract32((x)->word[0], 12, 2) +#define CMD_SSID(x) extract32((x)->word[0], 16, 16) +#define CMD_SID(x) ((x)->word[1]) +#define CMD_VMID(x) extract32((x)->word[1], 0, 16) +#define CMD_ASID(x) extract32((x)->word[1], 16, 16) +#define CMD_STAG(x) extract32((x)->word[2], 0, 16) +#define CMD_RESP(x) extract32((x)->word[2], 11, 2) +#define CMD_GRPID(x) extract32((x)->word[3], 0, 8) +#define CMD_SIZE(x) extract32((x)->word[3], 0, 16) +#define CMD_LEAF(x) extract32((x)->word[3], 0, 1) +#define CMD_SPAN(x) extract32((x)->word[3], 0, 5) +#define CMD_ADDR(x) ({ \ + uint64_t addr =3D (uint64_t)(x)->word[3]; \ + addr <<=3D 32; \ + addr |=3D extract32((x)->word[3], 12, 20); \ + addr; \ + }) + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 2f96463..f35fadc 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -72,7 +72,7 @@ static void smmuv3_irq_trigger(SMMUV3State *s, SMMUIrq ir= q, uint32_t gerror_val) } } =20 -void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerrorn) +static void smmuv3_write_gerrorn(SMMUV3State *s, uint32_t gerrorn) { uint32_t pending_gerrors =3D SMMU_PENDING_GERRORS(s); uint32_t sanitized; @@ -116,7 +116,7 @@ static void smmu_q_write(SMMUQueue *q, void *data) } } =20 -MemTxResult smmuv3_read_cmdq(SMMUV3State *s, Cmd *cmd) +static MemTxResult smmuv3_read_cmdq(SMMUV3State *s, Cmd *cmd) { SMMUQueue *q =3D &s->cmdq; MemTxResult ret =3D smmu_q_read(q, cmd); @@ -224,6 +224,147 @@ static inline void smmu_update_base_reg(SMMUV3State *= s, uint64_t *base, *base =3D val & ~(SMMU_BASE_RA | 0x3fULL); } =20 +static int smmuv3_cmdq_consume(SMMUV3State *s) +{ + SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; + + trace_smmuv3_cmdq_consume(SMMU_CMDQ_ERR(s), smmu_cmd_q_enabled(s), + s->cmdq.prod, s->cmdq.cons, + s->cmdq.wrap.prod, s->cmdq.wrap.cons); + + if (!smmu_cmd_q_enabled(s)) { + return 0; + } + + while (!SMMU_CMDQ_ERR(s) && !smmu_is_q_empty(s, &s->cmdq)) { + uint32_t type; + Cmd cmd; + + if (smmuv3_read_cmdq(s, &cmd) !=3D MEMTX_OK) { + cmd_error =3D SMMU_CERROR_ABT; + break; + } + + type =3D CMD_TYPE(&cmd); + + trace_smmuv3_cmdq_opcode(cmd_stringify[type]); + + switch (CMD_TYPE(&cmd)) { + case SMMU_CMD_SYNC: + if (CMD_CS(&cmd) & CMD_SYNC_SIG_IRQ) { + smmuv3_irq_trigger(s, SMMU_IRQ_CMD_SYNC, 0); + } + break; + case SMMU_CMD_PREFETCH_CONFIG: + case SMMU_CMD_PREFETCH_ADDR: + break; + case SMMU_CMD_CFGI_STE: + { + uint32_t streamid =3D cmd.word[1]; + + trace_smmuv3_cmdq_cfgi_ste(streamid); + break; + } + case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */ + { + uint32_t start =3D cmd.word[1], range, end; + + range =3D extract32(cmd.word[2], 0, 5); + end =3D start + (1 << (range + 1)) - 1; + trace_smmuv3_cmdq_cfgi_ste_range(start, end); + break; + } + case SMMU_CMD_CFGI_CD: + case SMMU_CMD_CFGI_CD_ALL: + trace_smmuv3_unhandled_cmd(type); + break; + case SMMU_CMD_TLBI_NH_ALL: + case SMMU_CMD_TLBI_NH_ASID: + trace_smmuv3_unhandled_cmd(type); + break; + case SMMU_CMD_TLBI_NH_VA: + { + int asid =3D extract32(cmd.word[1], 16, 16); + int vmid =3D extract32(cmd.word[1], 0, 16); + uint64_t low =3D extract32(cmd.word[2], 12, 20); + uint64_t high =3D cmd.word[3]; + uint64_t addr =3D high << 32 | (low << 12); + + trace_smmuv3_cmdq_tlbi_nh_va(asid, vmid, addr); + break; + } + case SMMU_CMD_TLBI_NH_VAA: + case SMMU_CMD_TLBI_EL3_ALL: + case SMMU_CMD_TLBI_EL3_VA: + case SMMU_CMD_TLBI_EL2_ALL: + case SMMU_CMD_TLBI_EL2_ASID: + case SMMU_CMD_TLBI_EL2_VA: + case SMMU_CMD_TLBI_EL2_VAA: + case SMMU_CMD_TLBI_S12_VMALL: + case SMMU_CMD_TLBI_S2_IPA: + case SMMU_CMD_TLBI_NSNH_ALL: + trace_smmuv3_unhandled_cmd(type); + break; + case SMMU_CMD_ATC_INV: + case SMMU_CMD_PRI_RESP: + case SMMU_CMD_RESUME: + case SMMU_CMD_STALL_TERM: + trace_smmuv3_unhandled_cmd(type); + break; + default: + cmd_error =3D SMMU_CERROR_ILL; + error_report("Illegal command type: %d", CMD_TYPE(&cmd)); + break; + } + } + + if (cmd_error) { + error_report("GERROR_CMDQ: CONS.ERR=3D%d", cmd_error); + smmu_write_cmdq_err(s, cmd_error); + smmuv3_irq_trigger(s, SMMU_IRQ_GERROR, SMMU_GERROR_CMDQ); + } + + trace_smmuv3_cmdq_consume_out(s->cmdq.wrap.prod, s->cmdq.prod, + s->cmdq.wrap.cons, s->cmdq.cons); + + return 0; +} + +static void smmu_update_qreg(SMMUV3State *s, SMMUQueue *q, hwaddr reg, + uint32_t off, uint64_t val, unsigned size) +{ + if (size =3D=3D 8 && off =3D=3D 0) { + smmu_write64_reg(s, reg, val); + } else { + smmu_write32_reg(s, reg, val); + } + + switch (off) { + case 0: /* BASE register */ + val =3D smmu_read64_reg(s, reg); + q->shift =3D val & 0x1f; + q->entries =3D 1 << (q->shift); + smmu_update_base_reg(s, &q->base, val); + break; + + case 8: /* PROD */ + q->prod =3D Q_IDX(q, val); + q->wrap.prod =3D val >> q->shift; + break; + + case 12: /* CONS */ + q->cons =3D Q_IDX(q, val); + q->wrap.cons =3D val >> q->shift; + trace_smmuv3_update_qreg(q->cons, val); + break; + + } + + if (reg =3D=3D SMMU_REG_CMDQ_PROD) { + smmuv3_cmdq_consume(s); + } +} + static void smmu_write_mmio_fixup(SMMUV3State *s, hwaddr *addr) { switch (*addr) { @@ -236,6 +377,65 @@ static void smmu_write_mmio_fixup(SMMUV3State *s, hwad= dr *addr) static void smmu_write_mmio(void *opaque, hwaddr addr, uint64_t val, unsigned size) { + SMMUState *sys =3D opaque; + SMMUV3State *s =3D SMMU_V3_DEV(sys); + + smmu_write_mmio_fixup(s, &addr); + + trace_smmuv3_write_mmio(addr, val, size); + + switch (addr) { + case 0xFDC ... 0xFFC: + case SMMU_REG_IDR0 ... SMMU_REG_IDR5: + trace_smmuv3_write_mmio_idr(addr, val); + return; + case SMMU_REG_GERRORN: + smmuv3_write_gerrorn(s, val); + /* + * By acknowledging the CMDQ_ERR, SW may notify cmds can + * be processed again + */ + smmuv3_cmdq_consume(s); + return; + case SMMU_REG_CR0: + smmu_write32_reg(s, SMMU_REG_CR0, val); + /* immediatly reflect the changes in CR0_ACK */ + smmu_write32_reg(s, SMMU_REG_CR0_ACK, val); + /* in case the command queue has been enabled */ + smmuv3_cmdq_consume(s); + return; + case SMMU_REG_IRQ_CTRL: + smmu_write32_reg(s, SMMU_REG_IRQ_CTRL_ACK, val); + return; + case SMMU_REG_STRTAB_BASE: + smmu_update_base_reg(s, &s->strtab_base, val); + return; + case SMMU_REG_STRTAB_BASE_CFG: + if (((val >> 16) & 0x3) =3D=3D 0x1) { + s->sid_split =3D (val >> 6) & 0x1f; + s->features |=3D SMMU_FEATURE_2LVL_STE; + } + return; + case SMMU_REG_CMDQ_BASE ... SMMU_REG_CMDQ_CONS: + smmu_update_qreg(s, &s->cmdq, addr, addr - SMMU_REG_CMDQ_BASE, + val, size); + return; + + case SMMU_REG_EVTQ_BASE ... SMMU_REG_EVTQ_CONS: + smmu_update_qreg(s, &s->evtq, addr, addr - SMMU_REG_EVTQ_BASE, + val, size); + return; + + case SMMU_REG_PRIQ_BASE ... SMMU_REG_PRIQ_CONS: + error_report("%s PRI queue is not supported", __func__); + abort(); + } + + if (size =3D=3D 8) { + smmu_write64_reg(s, addr, val); + } else { + smmu_write32_reg(s, addr, (uint32_t)val); + } } =20 static uint64_t smmu_read_mmio(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/arm/trace-events b/hw/arm/trace-events index c1ce8eb..40f2057 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -19,3 +19,18 @@ smmu_set_translated_address(hwaddr iova, hwaddr pa) "iov= a =3D 0x%"PRIx64" -> pa =3D smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx= 64" val:0x%"PRIx64" size: 0x%x" smmuv3_irq_trigger(int irq, uint32_t gerror, uint32_t pending) "irq=3D%d g= error=3D0x%x pending gerrors=3D0x%x" smmuv3_write_gerrorn(uint32_t gerrorn, uint32_t sanitized, uint32_t pendin= g) "gerrorn=3D0x%x sanitized=3D0x%x pending=3D0x%x" +smmuv3_unhandled_cmd(uint32_t type) "Unhandled command type=3D%d" +smmuv3_cmdq_consume(int error, bool enabled, uint32_t prod, uint32_t cons,= uint8_t wrap_prod, uint8_t wrap_cons) "error=3D%d, enabled=3D%d prod=3D%d = cons=3D%d wrap.prod=3D%d wrap.cons=3D%d" +smmuv3_cmdq_consume_details(hwaddr base, uint32_t cons, uint32_t prod, uin= t32_t word, uint8_t wrap_cons) "CMDQ base: 0x%"PRIx64" cons:%d prod:%d val:= 0x%x wrap:%d" +smmuv3_cmdq_opcode(const char *opcode) "<--- %s" +smmuv3_cmdq_cfgi_ste(int streamid) " |_ streamid =3D%d" +smmuv3_cmdq_cfgi_ste_range(int start, int end) " |_ start=3D0x%d - end= =3D0x%d" +smmuv3_cmdq_tlbi_nh_va(int asid, int vmid, uint64_t addr) " |_ asid = =3D%d vmid =3D%d addr=3D0x%"PRIx64 +smmuv3_cmdq_consume_out(uint8_t prod_wrap, uint32_t prod, uint8_t cons_wra= p, uint32_t cons) "prod_wrap:%d, prod:0x%x cons_wrap:%d cons:0x%x" +smmuv3_update(bool is_empty, uint32_t prod, uint32_t cons, uint8_t prod_wr= ap, uint8_t cons_wrap) "q empty:%d prod:%d cons:%d p.wrap:%d p.cons:%d" +smmuv3_update_check_cmd(int error) "cmdq not enabled or error :0x%x" +smmuv3_update_qreg(uint32_t cons, uint64_t val) "cons written : %d val:0x%= "PRIx64 +smmuv3_write_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRI= x64" val:0x%"PRIx64" size: 0x%x" +smmuv3_write_mmio_idr(hwaddr addr, uint64_t val) "write to RO/Unimpl reg 0= x%lx val64:0x%lx" +smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_= t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0= x%x prod.w:%d cons.w:%d" +smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint= 8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:= 0x%x prod.w:%d cons.w:%d" --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287184153196.241689913826; Fri, 1 Sep 2017 10:33:04 -0700 (PDT) Received: from localhost ([::1]:51361 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpoV-0006xJ-3h for importer@patchew.org; Fri, 01 Sep 2017 13:33:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37109) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpf0-0005lg-PU for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpev-0003Dq-Oe for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55408) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpen-000369-3c; Fri, 01 Sep 2017 13:23:01 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 16CFA61481; Fri, 1 Sep 2017 17:23:00 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id A6D4C669FC; Fri, 1 Sep 2017 17:22:47 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 16CFA61481 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=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:12 +0200 Message-Id: <1504286483-23327-10-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 01 Sep 2017 17:23:00 +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] [PATCH v7 09/20] hw/arm/smmuv3: Event queue recording helper 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, wtownsen@redhat.com 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" Let's introduce a helper function aiming at recording an event in the event queue. Signed-off-by: Eric Auger --- At the moment, for some events we do not fill all the fields. Typically filling the FetchAddr field resulting of an abort on page table walk would require to return more information from this latter in case of error. However with enabled use cases I have not seen any event recorded yet. --- hw/arm/smmuv3-internal.h | 45 ++++++++++++++++++++++++-- hw/arm/smmuv3.c | 84 ++++++++++++++++++++++++++++++++++++++++++++= +++- 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index a5d60b4..e3e9828 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -259,8 +259,6 @@ static inline void smmu_write_cmdq_err(SMMUV3State *s, = uint32_t err_type) regval | err_type << SMMU_CMD_CONS_ERR_SHIFT); } =20 -void smmuv3_write_evtq(SMMUV3State *s, Evt *evt); - /***************************** * Commands *****************************/ @@ -361,4 +359,47 @@ enum { /* Command completion notification */ addr; \ }) =20 +/***************************** + * EVTQ fields + *****************************/ + +#define EVT_Q_OVERFLOW (1 << 31) + +#define EVT_SET_TYPE(x, t) deposit32((x)->word[0], 0, 8, t) +#define EVT_SET_SID(x, s) ((x)->word[1] =3D s) +#define EVT_SET_INPUT_ADDR(x, addr) ({ \ + (x)->word[5] =3D (uint32_t)(addr >> 32); \ + (x)->word[4] =3D (uint32_t)(addr & 0xffffffff); \ + }) +#define EVT_SET_RNW(x, rnw) deposit32((x)->word[3], 3, 1, rnw) + +/***************************** + * Events + *****************************/ + +typedef enum evt_err { + SMMU_EVT_OK, + SMMU_EVT_F_UUT, + SMMU_EVT_C_BAD_SID, + SMMU_EVT_F_STE_FETCH, + SMMU_EVT_C_BAD_STE, + SMMU_EVT_F_BAD_ATS_REQ, + SMMU_EVT_F_STREAM_DISABLED, + SMMU_EVT_F_TRANS_FORBIDDEN, + SMMU_EVT_C_BAD_SSID, + SMMU_EVT_F_CD_FETCH, + SMMU_EVT_C_BAD_CD, + SMMU_EVT_F_WALK_EXT_ABRT, + SMMU_EVT_F_TRANS =3D 0x10, + SMMU_EVT_F_ADDR_SZ, + SMMU_EVT_F_ACCESS, + SMMU_EVT_F_PERM, + SMMU_EVT_F_TLB_CONFLICT =3D 0x20, + SMMU_EVT_F_CFG_CONFLICT =3D 0x21, + SMMU_EVT_E_PAGE_REQ =3D 0x24, +} SMMUEvtErr; + +void smmuv3_record_event(SMMUV3State *s, hwaddr iova, + uint32_t sid, bool is_write, SMMUEvtErr type); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index f35fadc..7470576 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -132,7 +132,7 @@ static MemTxResult smmuv3_read_cmdq(SMMUV3State *s, Cmd= *cmd) return ret; } =20 -void smmuv3_write_evtq(SMMUV3State *s, Evt *evt) +static void smmuv3_write_evtq(SMMUV3State *s, Evt *evt) { SMMUQueue *q =3D &s->evtq; bool was_empty =3D smmu_is_q_empty(s, q); @@ -157,6 +157,88 @@ void smmuv3_write_evtq(SMMUV3State *s, Evt *evt) } } =20 +/* + * smmuv3_record_event - Record an event + */ +void smmuv3_record_event(SMMUV3State *s, hwaddr iova, + uint32_t sid, IOMMUAccessFlags perm, + SMMUEvtErr type) +{ + Evt evt; + bool rnw =3D perm & IOMMU_RO; + + if (!smmu_evt_q_enabled(s)) { + return; + } + + EVT_SET_TYPE(&evt, type); + EVT_SET_SID(&evt, sid); + /* SSV=3D0 (substream invalid) and substreamID=3D 0 */ + + switch (type) { + case SMMU_EVT_OK: + return; + case SMMU_EVT_F_UUT: + EVT_SET_INPUT_ADDR(&evt, iova); + EVT_SET_RNW(&evt, rnw); + /* PnU and Ind not filled */ + break; + case SMMU_EVT_C_BAD_SID: + break; + case SMMU_EVT_F_STE_FETCH: + /* Implementation defined and FetchAddr not filled yet */ + break; + case SMMU_EVT_C_BAD_STE: + break; + case SMMU_EVT_F_BAD_ATS_REQ: + /* ATS not yet implemented */ + break; + case SMMU_EVT_F_STREAM_DISABLED: + break; + case SMMU_EVT_F_TRANS_FORBIDDEN: + EVT_SET_INPUT_ADDR(&evt, iova); + EVT_SET_RNW(&evt, rnw); + break; + case SMMU_EVT_C_BAD_SSID: + break; + case SMMU_EVT_F_CD_FETCH: + break; + case SMMU_EVT_C_BAD_CD: + /* Implementation defined and FetchAddr not filled yet */ + break; + case SMMU_EVT_F_WALK_EXT_ABRT: + EVT_SET_INPUT_ADDR(&evt, iova); + EVT_SET_RNW(&evt, rnw); + /* Reason, Class, S2, Ind, PnU, FetchAddr not filled yet */ + break; + case SMMU_EVT_F_TRANS: + case SMMU_EVT_F_ADDR_SZ: + case SMMU_EVT_F_ACCESS: + EVT_SET_INPUT_ADDR(&evt, iova); + EVT_SET_RNW(&evt, rnw); + /* STAG, Class, S2, InD, PnU, IPA not filled yet */ + break; + case SMMU_EVT_F_PERM: + EVT_SET_INPUT_ADDR(&evt, iova); + EVT_SET_RNW(&evt, rnw); + /* STAG, TTRnW, Class, S2, InD, PnU, IPA not filled yet */ + break; + case SMMU_EVT_F_TLB_CONFLICT: + EVT_SET_INPUT_ADDR(&evt, iova); + EVT_SET_RNW(&evt, rnw); + /* Reason, S2, InD, PnU, IPA not filled yet */ + break; + case SMMU_EVT_F_CFG_CONFLICT: + /* Implementation defined reason not filled yet */ + break; + case SMMU_EVT_E_PAGE_REQ: + /* PRI not supported */ + break; + } + + smmuv3_write_evtq(s, &evt); +} + static void smmuv3_init_regs(SMMUV3State *s) { uint32_t data =3D --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287146323478.9905942153198; Fri, 1 Sep 2017 10:32:26 -0700 (PDT) Received: from localhost ([::1]:51347 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpnp-0006NA-At for importer@patchew.org; Fri, 01 Sep 2017 13:32:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37154) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpf3-0005oT-Ho for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpf1-0003Ih-4Z for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:17 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55524) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpes-0003An-Cb; Fri, 01 Sep 2017 13:23:06 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 58434806B6; Fri, 1 Sep 2017 17:23:05 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6E71962929; Fri, 1 Sep 2017 17:23:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 58434806B6 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:13 +0200 Message-Id: <1504286483-23327-11-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 01 Sep 2017 17:23:05 +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] [PATCH v7 10/20] hw/arm/smmuv3: Implement translate callback 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, wtownsen@redhat.com 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 implements the IOMMU Memory Region translate() callback. Most of the code relates to the translation configuration decoding and check (STE, CD). Signed-off-by: Eric Auger --- hw/arm/smmuv3-internal.h | 182 +++++++++++++++++++++++- hw/arm/smmuv3.c | 351 +++++++++++++++++++++++++++++++++++++++++++= +++- hw/arm/trace-events | 9 ++ 3 files changed, 537 insertions(+), 5 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index e3e9828..f9f95ae 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -399,7 +399,185 @@ typedef enum evt_err { SMMU_EVT_E_PAGE_REQ =3D 0x24, } SMMUEvtErr; =20 -void smmuv3_record_event(SMMUV3State *s, hwaddr iova, - uint32_t sid, bool is_write, SMMUEvtErr type); +/***************************** + * Configuration Data + *****************************/ + +typedef struct __smmu_data2 STEDesc; /* STE Level 1 Descriptor */ +typedef struct __smmu_data16 Ste; /* Stream Table Entry(STE) */ +typedef struct __smmu_data2 CDDesc; /* CD Level 1 Descriptor */ +typedef struct __smmu_data16 Cd; /* Context Descriptor(CD) */ + +/***************************** + * STE fields + *****************************/ + +#define STE_VALID(x) extract32((x)->word[0], 0, 1) /* 0 */ +#define STE_CONFIG(x) extract32((x)->word[0], 1, 3) +enum { + STE_CONFIG_NONE =3D 0, + STE_CONFIG_BYPASS =3D 4, /* S1 Bypass , S2 Bypass */ + STE_CONFIG_S1 =3D 5, /* S1 Translate , S2 Bypass */ + STE_CONFIG_S2 =3D 6, /* S1 Bypass , S2 Translate */ + STE_CONFIG_NESTED =3D 7, /* S1 Translate , S2 Translate */ +}; +#define STE_S1FMT(x) extract32((x)->word[0], 4, 2) +#define STE_S1CDMAX(x) extract32((x)->word[1], 27, 5) +#define STE_EATS(x) extract32((x)->word[2], 28, 2) +#define STE_STRW(x) extract32((x)->word[2], 30, 2) +#define STE_S2VMID(x) extract32((x)->word[4], 0, 16) +#define STE_S2T0SZ(x) extract32((x)->word[5], 0, 6) +#define STE_S2SL0(x) extract32((x)->word[5], 6, 2) +#define STE_S2TG(x) extract32((x)->word[5], 14, 2) +#define STE_S2PS(x) extract32((x)->word[5], 16, 3) +#define STE_S2AA64(x) extract32((x)->word[5], 19, 1) +#define STE_S2HD(x) extract32((x)->word[5], 24, 1) +#define STE_S2HA(x) extract32((x)->word[5], 25, 1) +#define STE_S2S(x) extract32((x)->word[5], 26, 1) +#define STE_CTXPTR(x) \ + ({ \ + unsigned long addr; \ + addr =3D (uint64_t)extract32((x)->word[1], 0, 16) << 32; \ + addr |=3D (uint64_t)((x)->word[0] & 0xffffffc0); \ + addr; \ + }) + +#define STE_S2TTB(x) \ + ({ \ + unsigned long addr; \ + addr =3D (uint64_t)extract32((x)->word[7], 0, 16) << 32; \ + addr |=3D (uint64_t)((x)->word[6] & 0xfffffff0); \ + addr; \ + }) + +static inline int is_ste_bypass(Ste *ste) +{ + return STE_CONFIG(ste) =3D=3D STE_CONFIG_BYPASS; +} + +static inline bool is_ste_stage1(Ste *ste) +{ + return STE_CONFIG(ste) =3D=3D STE_CONFIG_S1; +} + +static inline bool is_ste_stage2(Ste *ste) +{ + return STE_CONFIG(ste) =3D=3D STE_CONFIG_S2; +} + +/** + * is_s2granule_valid - Check the stage 2 translation granule size + * advertised in the STE matches any IDR5 supported value + */ +static inline bool is_s2granule_valid(Ste *ste) +{ + int idr5_format =3D 0; + + switch (STE_S2TG(ste)) { + case 0: /* 4kB */ + idr5_format =3D 0x1; + break; + case 1: /* 64 kB */ + idr5_format =3D 0x4; + break; + case 2: /* 16 kB */ + idr5_format =3D 0x2; + break; + case 3: /* reserved */ + break; + } + idr5_format &=3D SMMU_IDR5_GRAN; + return idr5_format; +} + +static inline int oas2bits(int oas_field) +{ + switch (oas_field) { + case 0b011: + return 42; + case 0b100: + return 44; + default: + return 32 + (1 << oas_field); + } +} + +static inline int pa_range(Ste *ste) +{ + int oas_field =3D MIN(STE_S2PS(ste), SMMU_IDR5_OAS); + + if (!STE_S2AA64(ste)) { + return 40; + } + + return oas2bits(oas_field); +} + +#define MAX_PA(ste) ((1 << pa_range(ste)) - 1) + +/***************************** + * CD fields + *****************************/ +#define CD_VALID(x) extract32((x)->word[0], 30, 1) +#define CD_ASID(x) extract32((x)->word[1], 16, 16) +#define CD_TTB(x, sel) \ + ({ \ + uint64_t hi, lo; \ + hi =3D extract32((x)->word[(sel) * 2 + 3], 0, 16); \ + hi <<=3D 32; \ + lo =3D (x)->word[(sel) * 2 + 2] & ~0xf; \ + hi | lo; \ + }) + +#define CD_TSZ(x, sel) extract32((x)->word[0], (16 * (sel)) + 0, 6) +#define CD_TG(x, sel) extract32((x)->word[0], (16 * (sel)) + 6, 2) +#define CD_EPD(x, sel) extract32((x)->word[0], (16 * (sel)) + 14, 1) + +#define CD_T0SZ(x) CD_TSZ((x), 0) +#define CD_T1SZ(x) CD_TSZ((x), 1) +#define CD_TG0(x) CD_TG((x), 0) +#define CD_TG1(x) CD_TG((x), 1) +#define CD_EPD0(x) CD_EPD((x), 0) +#define CD_EPD1(x) CD_EPD((x), 1) +#define CD_IPS(x) extract32((x)->word[1], 0, 3) +#define CD_AARCH64(x) extract32((x)->word[1], 9, 1) +#define CD_TTB0(x) CD_TTB((x), 0) +#define CD_TTB1(x) CD_TTB((x), 1) + +#define CDM_VALID(x) ((x)->word[0] & 0x1) + +static inline int is_cd_valid(SMMUV3State *s, Ste *ste, Cd *cd) +{ + return CD_VALID(cd); +} + +/** + * tg2granule - Decodes the CD translation granule size field according + * to the TT in use + * @bits: TG0/1 fiels + * @tg1: if set, @bits belong to TG1, otherwise belong to TG0 + */ +static inline int tg2granule(int bits, bool tg1) +{ + switch (bits) { + case 1: + return tg1 ? 14 : 16; + case 2: + return tg1 ? 12 : 14; + case 3: + return tg1 ? 16 : 12; + default: + return 12; + } +} + +#define L1STD_L2PTR(stm) ({ \ + uint64_t hi, lo; \ + hi =3D (stm)->word[1]; \ + lo =3D (stm)->word[0] & ~(uint64_t)0x1f; \ + hi << 32 | lo; \ + }) + +#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4)) =20 #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 7470576..20fbce6 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -160,9 +160,9 @@ static void smmuv3_write_evtq(SMMUV3State *s, Evt *evt) /* * smmuv3_record_event - Record an event */ -void smmuv3_record_event(SMMUV3State *s, hwaddr iova, - uint32_t sid, IOMMUAccessFlags perm, - SMMUEvtErr type) +static void smmuv3_record_event(SMMUV3State *s, hwaddr iova, + uint32_t sid, IOMMUAccessFlags perm, + SMMUEvtErr type) { Evt evt; bool rnw =3D perm & IOMMU_RO; @@ -306,6 +306,348 @@ static inline void smmu_update_base_reg(SMMUV3State *= s, uint64_t *base, *base =3D val & ~(SMMU_BASE_RA | 0x3fULL); } =20 +/* + * All SMMU data structures are little endian, and are aligned to 8 bytes + * L1STE/STE/L1CD/CD, Queue entries in CMDQ/EVTQ/PRIQ + */ +static inline int smmu_get_ste(SMMUV3State *s, hwaddr addr, Ste *buf) +{ + trace_smmuv3_get_ste(addr); + return dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf)); +} + +/* + * For now we only support CD with a single entry, 'ssid' is used to ident= ify + * otherwise + */ +static inline int smmu_get_cd(SMMUV3State *s, Ste *ste, uint32_t ssid, Cd = *buf) +{ + hwaddr addr =3D STE_CTXPTR(ste); + + if (STE_S1CDMAX(ste) !=3D 0) { + error_report("Multilevel Ctx Descriptor not supported yet"); + } + + trace_smmuv3_get_cd(addr); + return dma_memory_read(&address_space_memory, addr, buf, sizeof(*buf)); +} + +/** + * is_ste_consistent - Check validity of STE + * according to 6.2.1 Validity of STE + * TODO: check the relevance of each check and compliance + * with this spec chapter + */ +static bool is_ste_consistent(SMMUV3State *s, Ste *ste) +{ + uint32_t _config =3D STE_CONFIG(ste); + uint32_t ste_vmid, ste_eats, ste_s2s, ste_s1fmt, ste_s2aa64, ste_s1cdm= ax; + uint32_t ste_strw; + bool strw_unused, addr_out_of_range, granule_supported; + bool config[] =3D {_config & 0x1, _config & 0x2, _config & 0x3}; + + ste_vmid =3D STE_S2VMID(ste); + ste_eats =3D STE_EATS(ste); /* Enable PCIe ATS trans */ + ste_s2s =3D STE_S2S(ste); + ste_s1fmt =3D STE_S1FMT(ste); + ste_s2aa64 =3D STE_S2AA64(ste); + ste_s1cdmax =3D STE_S1CDMAX(ste); /*CD bit # S1ContextPtr */ + ste_strw =3D STE_STRW(ste); /* stream world control */ + + if (!STE_VALID(ste)) { + error_report("STE NOT valid"); + return false; + } + + granule_supported =3D is_s2granule_valid(ste); + + /* As S1/S2 combinations are supported do not check + * corresponding STE config values */ + + if (!config[2]) { + /* Report abort to device, no event recorded */ + error_report("STE config 0b000 not implemented"); + return false; + } + + if (!SMMU_IDR1_SIDSIZE && ste_s1cdmax && config[0] && + !SMMU_IDR0_CD2L && (ste_s1fmt =3D=3D 1 || ste_s1fmt =3D=3D 2)) { + error_report("STE inconsistant, CD mismatch"); + return false; + } + if (SMMU_IDR0_ATS && ((_config & 0x3) =3D=3D 0) && + ((ste_eats =3D=3D 2 && (_config !=3D 0x7 || ste_s2s)) || + (ste_eats =3D=3D 1 && !ste_s2s))) { + error_report("STE inconsistant, EATS/S2S mismatch"); + return false; + } + if (config[0] && (SMMU_IDR1_SIDSIZE && + (ste_s1cdmax > SMMU_IDR1_SIDSIZE))) { + error_report("STE inconsistant, SSID out of range"); + return false; + } + + strw_unused =3D (!SMMU_IDR0_S1P || !SMMU_IDR0_HYP || (_config =3D=3D 4= )); + + addr_out_of_range =3D STE_S2TTB(ste) > MAX_PA(ste); + + if (is_ste_stage2(ste)) { + if ((ste_s2aa64 && !is_s2granule_valid(ste)) || + (!ste_s2aa64 && !(SMMU_IDR0_TTF & 0x1)) || + (ste_s2aa64 && !(SMMU_IDR0_TTF & 0x2)) || + ((STE_S2HA(ste) || STE_S2HD(ste)) && !ste_s2aa64) || + ((STE_S2HA(ste) || STE_S2HD(ste)) && !SMMU_IDR0_HTTU) || + (STE_S2HD(ste) && (SMMU_IDR0_HTTU =3D=3D 1)) || addr_out_of_ra= nge) { + error_report("STE inconsistant"); + trace_smmuv3_is_ste_consistent(config[1], granule_supported, + addr_out_of_range, ste_s2aa64, + STE_S2HA(ste), STE_S2HD(ste), + STE_S2TTB(ste)); + return false; + } + } + if (SMMU_IDR0_S2P && (config[0] =3D=3D 0 && config[1]) && + (strw_unused || !ste_strw) && !SMMU_IDR0_VMID16 && !(ste_vmid >> 8= )) { + error_report("STE inconsistant, VMID out of range"); + return false; + } + return true; +} + +/** + * smmu_find_ste - Return the stream table entry associated + * to the sid + * + * @s: smmuv3 handle + * @sid: stream ID + * @ste: returned stream table entry + * + * Supports linear and 2-level stream table + * Return 0 on success or an SMMUEvtErr enum value otherwise + */ +static int smmu_find_ste(SMMUV3State *s, uint16_t sid, Ste *ste) +{ + hwaddr addr; + + trace_smmuv3_find_ste(sid, s->features, s->sid_split); + /* Check SID range */ + if (sid > (1 << s->sid_size)) { + return SMMU_EVT_C_BAD_SID; + } + if (s->features & SMMU_FEATURE_2LVL_STE) { + int l1_ste_offset, l2_ste_offset, max_l2_ste, span; + hwaddr l1ptr, l2ptr; + STEDesc l1std; + + l1_ste_offset =3D sid >> s->sid_split; + l2_ste_offset =3D sid & ((1 << s->sid_split) - 1); + l1ptr =3D (hwaddr)(s->strtab_base + l1_ste_offset * sizeof(l1std)); + smmu_read_sysmem(l1ptr, &l1std, sizeof(l1std), false); + span =3D L1STD_SPAN(&l1std); + + if (!span) { + /* l2ptr is not valid */ + error_report("invalid sid=3D%d (L1STD span=3D0)", sid); + return SMMU_EVT_C_BAD_SID; + } + max_l2_ste =3D (1 << span) - 1; + l2ptr =3D L1STD_L2PTR(&l1std); + trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset, + l2ptr, l2_ste_offset, max_l2_ste); + if (l2_ste_offset > max_l2_ste) { + error_report("l2_ste_offset=3D%d > max_l2_ste=3D%d", + l2_ste_offset, max_l2_ste); + return SMMU_EVT_C_BAD_STE; + } + addr =3D L1STD_L2PTR(&l1std) + l2_ste_offset * sizeof(*ste); + } else { + addr =3D s->strtab_base + sid * sizeof(*ste); + } + + if (smmu_get_ste(s, addr, ste)) { + error_report("Unable to Fetch STE"); + return SMMU_EVT_F_STE_FETCH; + } + + return 0; +} + +/** + * smmu_cfg_populate_s1 - Populate the stage 1 translation config + * from the context descriptor + */ +static int smmu_cfg_populate_s1(SMMUTransCfg *cfg, Cd *cd) +{ + bool s1a64 =3D CD_AARCH64(cd); + int epd0 =3D CD_EPD0(cd); + int tg; + + cfg->stage =3D 1; + tg =3D epd0 ? CD_TG1(cd) : CD_TG0(cd); + cfg->tsz =3D epd0 ? CD_T1SZ(cd) : CD_T0SZ(cd); + cfg->ttbr =3D epd0 ? CD_TTB1(cd) : CD_TTB0(cd); + cfg->oas =3D oas2bits(CD_IPS(cd)); + + if (s1a64) { + cfg->tsz =3D MIN(cfg->tsz, 39); + cfg->tsz =3D MAX(cfg->tsz, 16); + } + cfg->granule_sz =3D tg2granule(tg, epd0); + + cfg->oas =3D MIN(oas2bits(SMMU_IDR5_OAS), cfg->oas); + /* fix ttbr - make top bits zero*/ + cfg->ttbr =3D extract64(cfg->ttbr, 0, cfg->oas); + cfg->aa64 =3D s1a64; + cfg->initial_level =3D 4 - (64 - cfg->tsz - 4) / (cfg->granule_sz - 3= ); + + trace_smmuv3_cfg_stage(cfg->stage, cfg->oas, cfg->tsz, cfg->ttbr, + cfg->aa64, cfg->granule_sz, cfg->initial_level); + + return 0; +} + +/** + * smmu_cfg_populate_s2 - Populate the stage 2 translation config + * from the Stream Table Entry + */ +static int smmu_cfg_populate_s2(SMMUTransCfg *cfg, Ste *ste) +{ + bool s2a64 =3D STE_S2AA64(ste); + int default_initial_level; + int tg; + + cfg->stage =3D 2; + + tg =3D STE_S2TG(ste); + cfg->tsz =3D STE_S2T0SZ(ste); + cfg->ttbr =3D STE_S2TTB(ste); + cfg->oas =3D pa_range(ste); + + cfg->aa64 =3D s2a64; + + if (s2a64) { + cfg->tsz =3D MIN(cfg->tsz, 39); + cfg->tsz =3D MAX(cfg->tsz, 16); + } + cfg->granule_sz =3D tg2granule(tg, 0); + + cfg->oas =3D MIN(oas2bits(SMMU_IDR5_OAS), cfg->oas); + /* fix ttbr - make top bits zero*/ + cfg->ttbr =3D extract64(cfg->ttbr, 0, cfg->oas); + + default_initial_level =3D 4 - (64 - cfg->tsz - 4) / (cfg->granule_sz -= 3); + cfg->initial_level =3D ~STE_S2SL0(ste); + if (cfg->initial_level !=3D default_initial_level) { + error_report("%s concatenated translation tables at initial S2 loo= kup" + " not supported", __func__); + return SMMU_EVT_C_BAD_STE;; + } + + trace_smmuv3_cfg_stage(cfg->stage, cfg->oas, cfg->tsz, cfg->ttbr, + cfg->aa64, cfg->granule_sz, cfg->initial_level); + + return 0; +} + +/** + * smmuv3_decode_config - Prepare the translation configuration + * for the @mr iommu region + * @mr: iommu memory region the translation config must be prepared for + * @cfg: output translation configuration + * + * return 0 on success or an SMMUEvtErr enum value otherwise + */ +static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg) +{ + SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); + int sid =3D smmu_get_sid(sdev); + SMMUV3State *s =3D sdev->smmu; + Ste ste; + Cd cd; + int ret =3D 0; + + if (!smmu_enabled(s)) { + cfg->disabled =3D true; + return 0; + } + ret =3D smmu_find_ste(s, sid, &ste); + if (ret) { + return ret; + } + + if (!STE_VALID(&ste)) { + return SMMU_EVT_C_BAD_STE; + } + + switch (STE_CONFIG(&ste)) { + case STE_CONFIG_BYPASS: + cfg->bypassed =3D true; + return 0; + case STE_CONFIG_S1: + break; + case STE_CONFIG_S2: + break; + default: /* reserved, abort, nested */ + return SMMU_EVT_F_UUT; + } + + /* S1 or S2 */ + + if (!is_ste_consistent(s, &ste)) { + return SMMU_EVT_C_BAD_STE; + } + + if (is_ste_stage1(&ste)) { + ret =3D smmu_get_cd(s, &ste, 0, &cd); /* We dont have SSID yet */ + if (ret) { + return SMMU_EVT_F_CD_FETCH; + } + + if (!is_cd_valid(s, &ste, &cd)) { + return SMMU_EVT_C_BAD_CD; + } + return smmu_cfg_populate_s1(cfg, &cd); + } + + return smmu_cfg_populate_s2(cfg, &ste); +} + +static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, + IOMMUAccessFlags flag) +{ + SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); + SMMUV3State *s =3D sdev->smmu; + uint16_t sid =3D smmu_get_sid(sdev); + SMMUEvtErr ret; + SMMUTransCfg cfg =3D {}; + IOMMUTLBEntry entry =3D { + .target_as =3D &address_space_memory, + .iova =3D addr, + .translated_addr =3D addr, + .addr_mask =3D ~(hwaddr)0, + .perm =3D flag, + }; + + ret =3D smmuv3_decode_config(mr, &cfg); + if (ret || cfg.disabled || cfg.bypassed) { + goto out; + } + + entry.addr_mask =3D (1 << cfg.granule_sz) - 1; + + ret =3D smmu_translate(&cfg, &entry); + + trace_smmuv3_translate(mr->parent_obj.name, sid, addr, + entry.translated_addr, entry.perm, ret); +out: + if (ret) { + error_report("%s translation failed for iova=3D0x%"PRIx64, + mr->parent_obj.name, addr); + smmuv3_record_event(s, entry.iova, sid, flag, ret); + } + return entry; +} + static int smmuv3_cmdq_consume(SMMUV3State *s) { SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; @@ -621,6 +963,9 @@ static void smmuv3_class_init(ObjectClass *klass, void = *data) static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, void *data) { + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D smmuv3_translate; } =20 static const TypeInfo smmuv3_type_info =3D { diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 40f2057..e643fc3 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -34,3 +34,12 @@ smmuv3_write_mmio(hwaddr addr, uint64_t val, unsigned si= ze) "addr: 0x%"PRIx64" v smmuv3_write_mmio_idr(hwaddr addr, uint64_t val) "write to RO/Unimpl reg 0= x%lx val64:0x%lx" smmuv3_write_mmio_evtq_cons_bef_clear(uint32_t prod, uint32_t cons, uint8_= t prod_wrap, uint8_t cons_wrap) "Before clearing interrupt prod:0x%x cons:0= x%x prod.w:%d cons.w:%d" smmuv3_write_mmio_evtq_cons_after_clear(uint32_t prod, uint32_t cons, uint= 8_t prod_wrap, uint8_t cons_wrap) "after clearing interrupt prod:0x%x cons:= 0x%x prod.w:%d cons.w:%d" +smmuv3_is_ste_consistent(bool cfg, bool granule_supported, bool addr_oor, = uint32_t aa64, int s2ha, int s2hd, uint64_t s2ttb ) "config[1]:%d gran:%d a= ddr:%d aa64:%d s2ha:%d s2hd:%d s2ttb:0x%"PRIx64 +smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:= 0x%x features:0x%x, sid_split:0x%x" +smmuv3_find_ste_2lvl(uint64_t strtab_base, hwaddr l1ptr, int l1_ste_offset= , hwaddr l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%lx l1ptr= :0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_ste:%d" +smmuv3_get_ste(hwaddr addr) "STE addr: 0x%"PRIx64 +smmuv3_translate_bypass(const char *n, uint16_t sid, hwaddr addr, bool is_= write) "%s sid=3D%d bypass iova:0x%"PRIx64" is_write=3D%d" +smmuv3_translate_in(uint16_t sid, int pci_bus_num, hwaddr strtab_base) "SI= D:0x%x bus:%d strtab_base:0x%"PRIx64 +smmuv3_get_cd(hwaddr addr) "CD addr: 0x%"PRIx64 +smmuv3_translate(const char *n, uint16_t sid, hwaddr iova, hwaddr translat= ed, int perm, int ret) "%s sid=3D%d iova=3D0x%"PRIx64" translated=3D0x%"PRI= x64" perm=3D0x%x (%d)" +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" --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504286729974621.733473355862; Fri, 1 Sep 2017 10:25:29 -0700 (PDT) Received: from localhost ([::1]:51265 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnphA-0007Py-NG for importer@patchew.org; Fri, 01 Sep 2017 13:25:28 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37291) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfL-000653-7g for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpfK-0003Xt-3l for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55834) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpfA-0003RO-Su; Fri, 01 Sep 2017 13:23:25 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CA4A961483; Fri, 1 Sep 2017 17:23:23 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id B3ACD52FA0; Fri, 1 Sep 2017 17:23:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com CA4A961483 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=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:14 +0200 Message-Id: <1504286483-23327-12-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 01 Sep 2017 17:23:24 +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] [PATCH v7 11/20] target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route 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, wtownsen@redhat.com 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" In case the MSI is translated by an IOMMU we need to fixup the MSI route with the translated address. Signed-off-by: Eric Auger --- v5 -> v6: - use IOMMUMemoryRegionClass API It is still unclear to me if we need to register an IOMMUNotifier to handle any change in the MSI doorbell which would occur behind the scene and would not lead to any call to kvm_arch_fixup_msi_route(). --- target/arm/kvm.c | 27 +++++++++++++++++++++++++++ target/arm/trace-events | 3 +++ 2 files changed, 30 insertions(+) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 7c17f0d..a2fa948 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -20,8 +20,13 @@ #include "sysemu/kvm.h" #include "kvm_arm.h" #include "cpu.h" +#include "trace.h" #include "internals.h" #include "hw/arm/arm.h" +#include "hw/pci/pci.h" +#include "hw/pci/msi.h" +#include "hw/arm/smmu-common.h" +#include "hw/arm/smmuv3.h" #include "exec/memattrs.h" #include "exec/address-spaces.h" #include "hw/boards.h" @@ -662,6 +667,28 @@ int kvm_arm_vgic_probe(void) int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data, PCIDevice *d= ev) { + AddressSpace *as =3D pci_device_iommu_address_space(dev); + IOMMUMemoryRegionClass *imrc; + IOMMUTLBEntry entry; + SMMUDevice *sdev; + + if (as =3D=3D &address_space_memory) { + return 0; + } + + /* MSI doorbell address is translated by an IOMMU */ + sdev =3D container_of(as, SMMUDevice, as); + imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(&sdev->iommu); + + entry =3D imrc->translate(&sdev->iommu, address, IOMMU_WO); + + route->u.msi.address_lo =3D entry.translated_addr; + route->u.msi.address_hi =3D entry.translated_addr >> 32; + + trace_kvm_arm_fixup_msi_route(address, sdev->devfn, + sdev->iommu.parent_obj.name, + entry.translated_addr); + return 0; } =20 diff --git a/target/arm/trace-events b/target/arm/trace-events index 9e37131..8b3c220 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -8,3 +8,6 @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write= : timer %d value 0x%" arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value = 0x%" PRIx64 arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK= toggle, new irqstate %d" arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64 + +# target/arm/kvm.c +kvm_arm_fixup_msi_route(uint64_t iova, uint32_t devid, const char *name, u= int64_t gpa) "MSI addr =3D 0x%"PRIx64" is translated for devfn=3D%d through= %s into 0x%"PRIx64 --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504286887020548.6124881559347; Fri, 1 Sep 2017 10:28:07 -0700 (PDT) Received: from localhost ([::1]:51290 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpji-0001ah-1P for importer@patchew.org; Fri, 01 Sep 2017 13:28:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37439) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfa-0006IP-Dq for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpfV-0003hX-1X for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56054) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpfL-0003YY-8T; Fri, 01 Sep 2017 13:23:35 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 382CE6148E; Fri, 1 Sep 2017 17:23:34 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2E05F17100; Fri, 1 Sep 2017 17:23:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 382CE6148E 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=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:15 +0200 Message-Id: <1504286483-23327-13-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 01 Sep 2017 17:23:34 +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] [PATCH v7 12/20] hw/arm/smmuv3: Implement data structure and TLB invalidation notifications 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, wtownsen@redhat.com 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" When the guest invalidates data structure (STE, CD) or TLB we need to notify the IOMMU region notifiers. This allows vhost integration and also prepares for VFIO integration. Signed-off-by: Eric Auger --- v6 -> v7: - move SMMU_CMD_TLBI_NH_VA_AM in a separate patch - rationalize names and add some comments - fix devfn computation in smmuv3_replay_sid - direcly use smmuv3_notify_iova_range - move smmuv3_replay (used for VFIO) in a separate patch v5 -> v6: - use IOMMUMemoryRegion - handle implementation defined SMMU_CMD_TLBI_NH_VA_AM cmd (goes along with TLBI_ON_MAP FW quirk) - replay systematically unmap the whole range first - smmuv3_map_hook does not unmap anymore and the unmap is done before the replay - add and use smmuv3_context_device_invalidate instead of blindly replaying everything --- hw/arm/smmuv3.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++= ++-- hw/arm/trace-events | 5 ++ 2 files changed, 138 insertions(+), 4 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 20fbce6..8e7d10d 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -25,6 +25,7 @@ #include "exec/address-spaces.h" #include "trace.h" #include "qemu/error-report.h" +#include "exec/target_page.h" =20 #include "hw/arm/smmuv3.h" #include "smmuv3-internal.h" @@ -648,6 +649,123 @@ out: return entry; } =20 +static int smmuv3_notify_entry(IOMMUTLBEntry *entry, void *private) +{ + trace_smmuv3_notify_entry(entry->iova, entry->translated_addr, + entry->addr_mask, entry->perm); + memory_region_notify_one((IOMMUNotifier *)private, entry); + return 0; +} + +static void smmuv3_notify_iova_range(IOMMUMemoryRegion *mr, IOMMUNotifier = *n, + uint64_t iova, size_t size) +{ + SMMUTransCfg cfg =3D {}; + IOMMUTLBEntry entry; + int ret; + + trace_smmuv3_notify_iova_range(mr->parent_obj.name, iova, size, n); + ret =3D smmuv3_decode_config(mr, &cfg); + if (ret) { + error_report("%s error decoding the configuration for iommu mr=3D%= s", + __func__, mr->parent_obj.name); + } + + if (cfg.disabled || cfg.bypassed) { + return; + } + + /* first unmap */ + entry.target_as =3D &address_space_memory; + entry.iova =3D iova & ~(size - 1); + entry.addr_mask =3D size - 1; + entry.perm =3D IOMMU_NONE; + + memory_region_notify_one(n, &entry); + + /* then figure out if a new mapping needs to be applied */ + smmu_page_walk(&cfg, iova, iova + entry.addr_mask , false, + smmuv3_notify_entry, n); +} + +static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *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->parent_obj.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->parent_obj.name); + QLIST_REMOVE(node, next); + g_free(node); + } + return; + } + } +} +/* + * Replay all iommu memory regions attached to the smmu + */ +static void smmuv3_replay_all(SMMUState *s) +{ + SMMUNotifierNode *node; + + QLIST_FOREACH(node, &s->notifiers_list, next) { + trace_smmuv3_replay_mr(node->sdev->iommu.parent_obj.name); + memory_region_iommu_replay_all(&node->sdev->iommu); + } +} + +/* + * Replay the iommu memory region corresponding to a given streamid + */ +static void smmuv3_replay_sid(SMMUState *s, uint16_t sid) +{ + uint8_t bus_n, devfn; + SMMUPciBus *smmu_bus; + SMMUDevice *smmu; + + bus_n =3D PCI_BUS_NUM(sid); + smmu_bus =3D smmu_find_as_from_bus_num(s, bus_n); + if (smmu_bus) { + devfn =3D sid & 0xFF; + smmu =3D smmu_bus->pbdev[devfn]; + if (smmu) { + trace_smmuv3_replay_mr(smmu->iommu.parent_obj.name); + memory_region_iommu_replay_all(&smmu->iommu); + } + } +} + +static void smmuv3_replay_iova_range(SMMUState *s, uint64_t iova, size_t s= ize) +{ + SMMUNotifierNode *node; + + QLIST_FOREACH(node, &s->notifiers_list, next) { + IOMMUMemoryRegion *mr =3D &node->sdev->iommu; + IOMMUNotifier *n; + + IOMMU_NOTIFIER_FOREACH(n, mr) { + smmuv3_notify_iova_range(mr, n, iova, size); + } + } +} + static int smmuv3_cmdq_consume(SMMUV3State *s) { SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; @@ -687,24 +805,32 @@ static int smmuv3_cmdq_consume(SMMUV3State *s) uint32_t streamid =3D cmd.word[1]; =20 trace_smmuv3_cmdq_cfgi_ste(streamid); + smmuv3_replay_sid(&s->smmu_state, streamid); break; } case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */ { - uint32_t start =3D cmd.word[1], range, end; + uint32_t start =3D cmd.word[1], range, end, i; =20 range =3D extract32(cmd.word[2], 0, 5); end =3D start + (1 << (range + 1)) - 1; trace_smmuv3_cmdq_cfgi_ste_range(start, end); + for (i =3D start; i <=3D end; i++) { + smmuv3_replay_sid(&s->smmu_state, i); + } break; } case SMMU_CMD_CFGI_CD: case SMMU_CMD_CFGI_CD_ALL: - trace_smmuv3_unhandled_cmd(type); + { + uint32_t streamid =3D cmd.word[1]; + + smmuv3_replay_sid(&s->smmu_state, streamid); break; + } case SMMU_CMD_TLBI_NH_ALL: case SMMU_CMD_TLBI_NH_ASID: - trace_smmuv3_unhandled_cmd(type); + smmuv3_replay_all(&s->smmu_state); break; case SMMU_CMD_TLBI_NH_VA: { @@ -713,8 +839,10 @@ static int smmuv3_cmdq_consume(SMMUV3State *s) uint64_t low =3D extract32(cmd.word[2], 12, 20); uint64_t high =3D cmd.word[3]; uint64_t addr =3D high << 32 | (low << 12); + size_t size =3D qemu_target_page_size(); =20 trace_smmuv3_cmdq_tlbi_nh_va(asid, vmid, addr); + smmuv3_replay_iova_range(&s->smmu_state, addr, size); break; } case SMMU_CMD_TLBI_NH_VAA: @@ -727,7 +855,7 @@ static int smmuv3_cmdq_consume(SMMUV3State *s) case SMMU_CMD_TLBI_S12_VMALL: case SMMU_CMD_TLBI_S2_IPA: case SMMU_CMD_TLBI_NSNH_ALL: - trace_smmuv3_unhandled_cmd(type); + smmuv3_replay_all(&s->smmu_state); break; case SMMU_CMD_ATC_INV: case SMMU_CMD_PRI_RESP: @@ -966,6 +1094,7 @@ static void smmuv3_iommu_memory_region_class_init(Obje= ctClass *klass, IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); =20 imrc->translate =3D smmuv3_translate; + imrc->notify_flag_changed =3D smmuv3_notify_flag_changed; } =20 static const TypeInfo smmuv3_type_info =3D { diff --git a/hw/arm/trace-events b/hw/arm/trace-events index e643fc3..4ac264d 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -43,3 +43,8 @@ smmuv3_translate_in(uint16_t sid, int pci_bus_num, hwaddr= strtab_base) "SID:0x%x smmuv3_get_cd(hwaddr addr) "CD addr: 0x%"PRIx64 smmuv3_translate(const char *n, uint16_t sid, hwaddr iova, hwaddr translat= ed, int perm, int ret) "%s sid=3D%d iova=3D0x%"PRIx64" translated=3D0x%"PRI= x64" perm=3D0x%x (%d)" 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_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_mr(const char *name) "iommu mr=3D%s" +smmuv3_notify_entry(hwaddr iova, hwaddr pa, hwaddr mask, int perm) "iova= =3D0x%"PRIx64" pa=3D0x%" PRIx64" mask=3D0x%"PRIx64" perm=3D%d" +smmuv3_notify_iova_range(const char *name, uint64_t iova, size_t size, voi= d *n) "iommu mr=3D%s iova=3D0x%"PRIx64" size=3D0x%lx n=3D%p" --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287160374243.1117596153921; Fri, 1 Sep 2017 10:32:40 -0700 (PDT) Received: from localhost ([::1]:51354 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpo7-0006dE-5m for importer@patchew.org; Fri, 01 Sep 2017 13:32:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37482) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfe-0006N5-Qp for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpfd-0003oc-SN for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:23:54 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51656) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpfT-0003gH-Sh; Fri, 01 Sep 2017 13:23:44 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D9EC8C047B88; Fri, 1 Sep 2017 17:23:42 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8FA80627DE; Fri, 1 Sep 2017 17:23:34 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D9EC8C047B88 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:16 +0200 Message-Id: <1504286483-23327-14-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 01 Sep 2017 17:23:43 +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] [PATCH v7 13/20] hw/arm/smmuv3: Implement IOMMU memory region replay callback 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, wtownsen@redhat.com 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" memory_region_iommu_replay() is used for VFIO integration. However its default implementation is not adapted to SMMUv3 IOMMU memory region. Indeed the input address range is too huge and its execution is too slow as it calls the translate() callback on each granule. Let's implement the replay callback which hierarchically walk over the page table structure and notify only the segments that are populated with valid entries. Signed-off-by: Eric Auger --- hw/arm/smmuv3.c | 36 ++++++++++++++++++++++++++++++++++++ hw/arm/trace-events | 1 + 2 files changed, 37 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 8e7d10d..c43bd93 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -657,6 +657,41 @@ static int smmuv3_notify_entry(IOMMUTLBEntry *entry, v= oid *private) return 0; } =20 +/* Unmap the whole notifier's range */ +static void smmuv3_unmap_notifier_range(IOMMUNotifier *n) +{ + IOMMUTLBEntry entry; + hwaddr size =3D n->end - n->start + 1; + + entry.target_as =3D &address_space_memory; + entry.iova =3D n->start & ~(size - 1); + entry.perm =3D IOMMU_NONE; + entry.addr_mask =3D size - 1; + + memory_region_notify_one(n, &entry); +} + +static void smmuv3_replay(IOMMUMemoryRegion *mr, IOMMUNotifier *n) +{ + SMMUTransCfg cfg =3D {}; + int ret; + + trace_smmuv3_replay(mr->parent_obj.name, n, n->start, n->end); + smmuv3_unmap_notifier_range(n); + + ret =3D smmuv3_decode_config(mr, &cfg); + if (ret) { + error_report("%s error decoding the configuration for iommu mr=3D%= s", + __func__, mr->parent_obj.name); + } + + if (cfg.disabled || cfg.bypassed) { + return; + } + /* walk the page tables and replay valid entries */ + smmu_page_walk(&cfg, 0, (1ULL << (64 - cfg.tsz)) - 1, false, + smmuv3_notify_entry, n); +} static void smmuv3_notify_iova_range(IOMMUMemoryRegion *mr, IOMMUNotifier = *n, uint64_t iova, size_t size) { @@ -1095,6 +1130,7 @@ static void smmuv3_iommu_memory_region_class_init(Obj= ectClass *klass, =20 imrc->translate =3D smmuv3_translate; imrc->notify_flag_changed =3D smmuv3_notify_flag_changed; + imrc->replay =3D smmuv3_replay; } =20 static const TypeInfo smmuv3_type_info =3D { diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 4ac264d..15f84d6 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -46,5 +46,6 @@ smmuv3_cfg_stage(int s, uint32_t oas, uint32_t tsz, uint6= 4_t ttbr, bool aa64, ui 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_mr(const char *name) "iommu mr=3D%s" +smmuv3_replay(const char *name, void *n, hwaddr start, hwaddr end) "iommu = mr=3D%s notifier=3D%p [0x%"PRIx64",0x%"PRIx64"]" smmuv3_notify_entry(hwaddr iova, hwaddr pa, hwaddr mask, int perm) "iova= =3D0x%"PRIx64" pa=3D0x%" PRIx64" mask=3D0x%"PRIx64" perm=3D%d" smmuv3_notify_iova_range(const char *name, uint64_t iova, size_t size, voi= d *n) "iommu mr=3D%s iova=3D0x%"PRIx64" size=3D0x%lx n=3D%p" --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287345373222.33273027471387; Fri, 1 Sep 2017 10:35:45 -0700 (PDT) Received: from localhost ([::1]:51520 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpr6-0000wY-45 for importer@patchew.org; Fri, 01 Sep 2017 13:35:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37546) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfn-0006Ut-An for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpfj-0003rs-D0 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58028) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpfc-0003nS-Nr; Fri, 01 Sep 2017 13:23:52 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AD28B356CE; Fri, 1 Sep 2017 17:23:51 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3FCFA52FA0; Fri, 1 Sep 2017 17:23:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com AD28B356CE Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:17 +0200 Message-Id: <1504286483-23327-15-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 01 Sep 2017 17:23:51 +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] [PATCH v7 14/20] hw/arm/virt: Store the PCI host controller dt phandle 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, wtownsen@redhat.com 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" Let's allocate a phandle for the PCI host controller dt node and store this latter in the Virt Machine State. This will simplify fdt operations when we bind smmu and PCI host controller. Signed-off-by: Eric Auger --- hw/arm/virt.c | 5 ++++- include/hw/arm/virt.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6b7a0fe..39886c1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -991,7 +991,7 @@ static void create_pcie_irq_map(const VirtMachineState = *vms, 0x7 /* PCI irq */); } =20 -static void create_pcie(const VirtMachineState *vms, qemu_irq *pic) +static void create_pcie(VirtMachineState *vms, qemu_irq *pic) { hwaddr base_mmio =3D vms->memmap[VIRT_PCIE_MMIO].base; hwaddr size_mmio =3D vms->memmap[VIRT_PCIE_MMIO].size; @@ -1100,8 +1100,11 @@ static void create_pcie(const VirtMachineState *vms,= qemu_irq *pic) 2, base_mmio, 2, size_mmio); } =20 + vms->pcihost_phandle =3D qemu_fdt_alloc_phandle(vms->fdt); + qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1); create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename); + qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", vms->pcihost_phan= dle); =20 g_free(nodename); } diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 33b0ff3..ae2bf2c 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -105,6 +105,7 @@ typedef struct { uint32_t clock_phandle; uint32_t gic_phandle; uint32_t msi_phandle; + uint32_t pcihost_phandle; int psci_conduit; } VirtMachineState; =20 --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 150428742111014.146120127016502; Fri, 1 Sep 2017 10:37:01 -0700 (PDT) Received: from localhost ([::1]:51578 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpsK-0002DV-6M for importer@patchew.org; Fri, 01 Sep 2017 13:37:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37718) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpfz-0006gc-Dt for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpfv-00042e-ED for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45274) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpfl-0003tT-JA; Fri, 01 Sep 2017 13:24:01 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8D10A461E0; Fri, 1 Sep 2017 17:24:00 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 11A1917100; Fri, 1 Sep 2017 17:23:51 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 8D10A461E0 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:18 +0200 Message-Id: <1504286483-23327-16-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 01 Sep 2017 17:24:00 +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] [PATCH v7 15/20] hw/arm/sysbus-fdt: Pass the VirtMachineState to the node creation functions 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, wtownsen@redhat.com 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" The VirtMachineState contains some dt phandles that will be used in some node creation functions. For instance we plan to use the PCI host controller phandle in the smmu node creation function. So let's pass the VirtMachineState handle down to the node creation functions by enhancing the involved datatypes. Signed-off-by: Eric Auger --- hw/arm/sysbus-fdt.c | 3 +++ hw/arm/virt.c | 1 + include/hw/arm/sysbus-fdt.h | 2 ++ 3 files changed, 6 insertions(+) diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index d68e3dc..d92a983 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -36,6 +36,7 @@ #include "hw/vfio/vfio-platform.h" #include "hw/vfio/vfio-calxeda-xgmac.h" #include "hw/vfio/vfio-amd-xgbe.h" +#include "hw/arm/virt.h" #include "hw/arm/fdt.h" =20 /* @@ -47,6 +48,7 @@ typedef struct PlatformBusFDTData { int irq_start; /* index of the first IRQ usable by platform bus device= s */ const char *pbus_node_name; /* name of the platform bus node */ PlatformBusDevice *pbus; + VirtMachineState *vms; } PlatformBusFDTData; =20 /* @@ -514,6 +516,7 @@ static void add_all_platform_bus_fdt_nodes(ARMPlatformB= usFDTParams *fdt_params) .irq_start =3D irq_start, .pbus_node_name =3D node, .pbus =3D pbus, + .vms =3D fdt_params->vms, }; =20 /* Loop through all dynamic sysbus devices and create their node */ diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 39886c1..d7c28b0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1125,6 +1125,7 @@ static void create_platform_bus(VirtMachineState *vms= , qemu_irq *pic) fdt_params->system_params =3D &platform_bus_params; fdt_params->binfo =3D &vms->bootinfo; fdt_params->intc =3D "/intc"; + fdt_params->vms =3D vms; /* * register a machine init done notifier that creates the device tree * nodes of the platform bus and its children dynamic sysbus devices diff --git a/include/hw/arm/sysbus-fdt.h b/include/hw/arm/sysbus-fdt.h index e15bb81..f5feabc 100644 --- a/include/hw/arm/sysbus-fdt.h +++ b/include/hw/arm/sysbus-fdt.h @@ -25,6 +25,7 @@ #define HW_ARM_SYSBUS_FDT_H =20 #include "hw/arm/arm.h" +#include "hw/arm/virt.h" #include "qemu-common.h" #include "hw/sysbus.h" =20 @@ -48,6 +49,7 @@ typedef struct { const ARMPlatformBusSystemParams *system_params; struct arm_boot_info *binfo; const char *intc; /* parent interrupt controller name */ + VirtMachineState *vms; } ARMPlatformBusFDTParams; =20 /** --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287058897351.92176998746606; Fri, 1 Sep 2017 10:30:58 -0700 (PDT) Received: from localhost ([::1]:51333 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpmT-0004rB-QH for importer@patchew.org; Fri, 01 Sep 2017 13:30:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37808) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpg7-0006ng-0V for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpg2-00048P-B3 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:23 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58448) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpfs-0003zx-Hg; Fri, 01 Sep 2017 13:24:08 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 83F17267F2; Fri, 1 Sep 2017 17:24:07 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id E4D5F17100; Fri, 1 Sep 2017 17:24:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 83F17267F2 Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:19 +0200 Message-Id: <1504286483-23327-17-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 01 Sep 2017 17:24:07 +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] [PATCH v7 16/20] hw/arm/sysbus-fdt: Pass the platform bus base address in PlatformBusFDTData 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, wtownsen@redhat.com 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" The Base address of the platform bus may be useful for device node creation function. This is typically the case if the node creation function also prepares data for ACPI table generation. Signed-off-by: Eric Auger --- hw/arm/sysbus-fdt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index d92a983..f8c4909 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -46,6 +46,7 @@ typedef struct PlatformBusFDTData { void *fdt; /* device tree handle */ int irq_start; /* index of the first IRQ usable by platform bus device= s */ + hwaddr base; /* base address of the platform bus */ const char *pbus_node_name; /* name of the platform bus node */ PlatformBusDevice *pbus; VirtMachineState *vms; @@ -514,6 +515,7 @@ static void add_all_platform_bus_fdt_nodes(ARMPlatformB= usFDTParams *fdt_params) PlatformBusFDTData data =3D { .fdt =3D fdt, .irq_start =3D irq_start, + .base =3D addr, .pbus_node_name =3D node, .pbus =3D pbus, .vms =3D fdt_params->vms, --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287500795666.635027914177; Fri, 1 Sep 2017 10:38:20 -0700 (PDT) Received: from localhost ([::1]:51631 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnptb-0003d5-C0 for importer@patchew.org; Fri, 01 Sep 2017 13:38:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37963) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpgK-0006zK-9p for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpgG-0004JT-9S for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:36 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46096) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpg8-0004DB-7V; Fri, 01 Sep 2017 13:24:24 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2990D91FD5; Fri, 1 Sep 2017 17:24:23 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id DC27217100; Fri, 1 Sep 2017 17:24:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 2990D91FD5 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:20 +0200 Message-Id: <1504286483-23327-18-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 01 Sep 2017 17:24:23 +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] [PATCH v7 17/20] hw/arm/sysbus-fdt: Allow smmuv3 dynamic instantiation 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, wtownsen@redhat.com 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 adds a node creation function for the smmuv3. Using "-device smmuv3" it is now possible to get the iommu instantiated on ARM VIRT machine. The node creation function handles the creation of the smmuv3 node and also add the iommu-map property on the generic PCI host controller node. Signed-off-by: Eric Auger --- hw/arm/smmuv3.c | 2 + hw/arm/sysbus-fdt.c | 110 ++++++++++++++++++++++++++++++++++++++++++++----= ---- 2 files changed, 96 insertions(+), 16 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index c43bd93..9c8640f 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1121,6 +1121,8 @@ static void smmuv3_class_init(ObjectClass *klass, voi= d *data) dc->reset =3D smmu_reset; dc->vmsd =3D &vmstate_smmuv3; dc->realize =3D smmu_realize; + /* Supported by TYPE_VIRT_MACHINE */ + dc->user_creatable =3D true; } =20 static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index f8c4909..9bbfbde 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -36,6 +36,7 @@ #include "hw/vfio/vfio-platform.h" #include "hw/vfio/vfio-calxeda-xgmac.h" #include "hw/vfio/vfio-amd-xgbe.h" +#include "hw/arm/smmuv3.h" #include "hw/arm/virt.h" #include "hw/arm/fdt.h" =20 @@ -126,6 +127,31 @@ static HostProperty clock_copied_properties[] =3D { {"clock-output-names", true}, }; =20 +static char *fdt_get_node_path(void *fdt, int phandle) +{ + char *node_path =3D NULL; + int ret, node_offset, path_len =3D 16;; + + node_offset =3D fdt_node_offset_by_phandle(fdt, phandle); + if (node_offset <=3D 0) { + error_setg(&error_fatal, + "not able to locate clock handle %d in device tree", + phandle); + } + + node_path =3D g_malloc(path_len); + while ((ret =3D fdt_get_path(fdt, node_offset, node_path, path_len)) + =3D=3D -FDT_ERR_NOSPACE) { + path_len +=3D 16; + node_path =3D g_realloc(node_path, path_len); + } + if (ret < 0) { + g_free(node_path); + node_path =3D NULL; + } + return node_path; +} + /** * fdt_build_clock_node * @@ -142,24 +168,12 @@ static void fdt_build_clock_node(void *host_fdt, void= *guest_fdt, uint32_t host_phandle, uint32_t guest_phandle) { - char *node_path =3D NULL; - char *nodename; + char *node_path, *nodename; const void *r; - int ret, node_offset, prop_len, path_len =3D 16; + int prop_len; =20 - node_offset =3D fdt_node_offset_by_phandle(host_fdt, host_phandle); - if (node_offset <=3D 0) { - error_setg(&error_fatal, - "not able to locate clock handle %d in host device tree= ", - host_phandle); - } - node_path =3D g_malloc(path_len); - while ((ret =3D fdt_get_path(host_fdt, node_offset, node_path, path_le= n)) - =3D=3D -FDT_ERR_NOSPACE) { - path_len +=3D 16; - node_path =3D g_realloc(node_path, path_len); - } - if (ret < 0) { + node_path =3D fdt_get_node_path(host_fdt, host_phandle); + if (!node_path) { error_setg(&error_fatal, "not able to retrieve node path for clock handle %d", host_phandle); @@ -416,6 +430,69 @@ static int add_amd_xgbe_fdt_node(SysBusDevice *sbdev, = void *opaque) return 0; } =20 +static int add_smmuv3_fdt_node(SysBusDevice *sbdev, void *opaque) +{ + const char irq_names[] =3D "eventq\0priq\0cmdq-sync\0gerror"; + const char compat[] =3D "arm,smmu-v3"; + uint32_t reg_attr[2], irq_attr[12], smmu_phandle; + uint64_t mmio_base, irq_number; + PlatformBusFDTData *data =3D opaque; + const char *parent_node =3D data->pbus_node_name; + PlatformBusDevice *pbus =3D data->pbus; + VirtMachineState *vms =3D data->vms; + void *guest_fdt =3D data->fdt; + char *nodename, *node_path; + int i; + + mmio_base =3D platform_bus_get_mmio_addr(pbus, sbdev, 0); + nodename =3D g_strdup_printf("%s/%s@%" PRIx64, parent_node, + "smmuv3", mmio_base); + qemu_fdt_add_subnode(guest_fdt, nodename); + + qemu_fdt_setprop(guest_fdt, nodename, "compatible", compat, sizeof(com= pat)); + + reg_attr[0] =3D cpu_to_be32(mmio_base); + reg_attr[1] =3D cpu_to_be32(0x20000); + qemu_fdt_setprop(guest_fdt, nodename, "reg", + reg_attr, 2 * sizeof(uint32_t)); + + for (i =3D 0; i < 4; i++) { + irq_number =3D platform_bus_get_irqn(pbus, sbdev , i) + data->irq_= start; + irq_attr[3 * i] =3D cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI); + irq_attr[3 * i + 1] =3D cpu_to_be32(irq_number); + irq_attr[3 * i + 2] =3D cpu_to_be32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); + } + qemu_fdt_setprop(guest_fdt, nodename, "interrupts", + irq_attr, 4 * 3 * sizeof(uint32_t)); + qemu_fdt_setprop(guest_fdt, nodename, "interrupt-names", irq_names, + sizeof(irq_names)); + + qemu_fdt_setprop_cell(guest_fdt, nodename, "clocks", vms->clock_phandl= e); + qemu_fdt_setprop_string(guest_fdt, nodename, "clock-names", "apb_pclk"= ); + qemu_fdt_setprop(guest_fdt, nodename, "dma-coherent", NULL, 0); + + qemu_fdt_setprop_cell(guest_fdt, nodename, "#iommu-cells", 1); + + smmu_phandle =3D qemu_fdt_alloc_phandle(vms->fdt); + + qemu_fdt_setprop_cell(guest_fdt, nodename, "phandle", smmu_phandle); + + node_path =3D fdt_get_node_path(guest_fdt, vms->pcihost_phandle); + if (!node_path) { + error_setg(&error_fatal, + "not able to retrieve node path for pci ctlr phandle %d= ", + vms->pcihost_phandle); + } + + qemu_fdt_setprop_cells(guest_fdt, node_path, "iommu-map", + 0x0, smmu_phandle, 0x0, 0x10000); + + g_free(nodename); + g_free(node_path); + + return 0; +} + #endif /* CONFIG_LINUX */ =20 /* list of supported dynamic sysbus devices */ @@ -423,6 +500,7 @@ static const NodeCreationPair add_fdt_node_functions[] = =3D { #ifdef CONFIG_LINUX {TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node}, {TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node}, + {TYPE_SMMU_V3_DEV, add_smmuv3_fdt_node}, #endif {"", NULL}, /* last element */ }; --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287612534218.7836732441807; Fri, 1 Sep 2017 10:40:12 -0700 (PDT) Received: from localhost ([::1]:51937 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpvP-0005Su-Hw for importer@patchew.org; Fri, 01 Sep 2017 13:40:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38120) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpgV-0007A1-UP for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpgR-0004VR-Sq for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46638) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpgK-0004MN-Qq; Fri, 01 Sep 2017 13:24:37 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CC50691FD5; Fri, 1 Sep 2017 17:24:35 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8041417100; Fri, 1 Sep 2017 17:24:23 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com CC50691FD5 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:21 +0200 Message-Id: <1504286483-23327-19-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 01 Sep 2017 17:24:36 +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] [PATCH v7 18/20] hw/arm/virt-acpi-build: Add smmuv3 node in IORT table 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, wtownsen@redhat.com 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" From: Prem Mallappa This patch builds the smmuv3 node in the ACPI IORT table. As the smmu is dynamically instantianted using the platform bus, the dt node creation function fills the information used by the IORT table generation function (base address, base irq, type of the smmu). The RID space of the root complex, which spans 0x0-0x10000 maps to streamid space 0x0-0x10000 in smmuv3, which in turn maps to deviceid space 0x0-0x10000 in the ITS group. Signed-off-by: Prem Mallappa Signed-off-by: Eric Auger --- v6 -> v7: - adapt to the fact the smmuv3 now is dynamically instantiated. - inverse sync and gerror interrupts v2 -> v3: - integrate into the existing IORT table made up of ITS, RC nodes - take into account vms->smmu - match linux actbl2.h acpi_iort_smmu_v3 field names --- hw/arm/sysbus-fdt.c | 5 ++++ hw/arm/virt-acpi-build.c | 58 +++++++++++++++++++++++++++++++++++++++--= ---- include/hw/acpi/acpi-defs.h | 15 ++++++++++++ include/hw/arm/virt.h | 13 ++++++++++ 4 files changed, 84 insertions(+), 7 deletions(-) diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index 9bbfbde..4583acf 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -487,6 +487,11 @@ static int add_smmuv3_fdt_node(SysBusDevice *sbdev, vo= id *opaque) qemu_fdt_setprop_cells(guest_fdt, node_path, "iommu-map", 0x0, smmu_phandle, 0x0, 0x10000); =20 + vms->smmu_info.type =3D VIRT_IOMMU_SMMUV3; + vms->smmu_info.reg.base =3D data->base + mmio_base; + vms->smmu_info.reg.size =3D 0x20000; + vms->smmu_info.irq_base =3D irq_number; + g_free(nodename); g_free(node_path); =20 diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 3d78ff6..8395898 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -43,6 +43,7 @@ #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" #include "hw/arm/virt.h" +#include "hw/arm/smmuv3.h" #include "sysemu/numa.h" #include "kvm_arm.h" =20 @@ -393,19 +394,26 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, un= signed xsdt_tbl_offset) } =20 static void -build_iort(GArray *table_data, BIOSLinker *linker) +build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { - int iort_start =3D table_data->len; + int nb_nodes, iort_start =3D table_data->len; AcpiIortIdMapping *idmap; AcpiIortItsGroup *its; AcpiIortTable *iort; - size_t node_size, iort_length; + AcpiIortSmmu3 *smmu; + size_t node_size, iort_length, smmu_offset =3D 0; AcpiIortRC *rc; =20 iort =3D acpi_data_push(table_data, sizeof(*iort)); =20 + if (vms->smmu_info.type) { + nb_nodes =3D 3; /* RC, ITS, SMMUv3 */ + } else { + nb_nodes =3D 2; /* RC, ITS */ + } + iort_length =3D sizeof(*iort); - iort->node_count =3D cpu_to_le32(2); /* RC and ITS nodes */ + iort->node_count =3D cpu_to_le32(nb_nodes); iort->node_offset =3D cpu_to_le32(sizeof(*iort)); =20 /* ITS group node */ @@ -418,6 +426,36 @@ build_iort(GArray *table_data, BIOSLinker *linker) its->its_count =3D cpu_to_le32(1); its->identifiers[0] =3D 0; /* MADT translation_id */ =20 + if (vms->smmu_info.type =3D=3D VIRT_IOMMU_SMMUV3) { + int irq =3D vms->smmu_info.irq_base; + + /* SMMUv3 node */ + smmu_offset =3D cpu_to_le32(iort->node_offset + node_size); + node_size =3D sizeof(*smmu) + sizeof(*idmap); + iort_length +=3D node_size; + smmu =3D acpi_data_push(table_data, node_size); + + + smmu->type =3D ACPI_IORT_NODE_SMMU_V3; + smmu->length =3D cpu_to_le16(node_size); + smmu->mapping_count =3D cpu_to_le32(1); + smmu->mapping_offset =3D cpu_to_le32(sizeof(*smmu)); + smmu->base_address =3D cpu_to_le64(vms->smmu_info.reg.base); + smmu->event_gsiv =3D cpu_to_le32(irq); + smmu->pri_gsiv =3D cpu_to_le32(irq + 1); + smmu->sync_gsiv =3D cpu_to_le32(irq + 2); + smmu->gerr_gsiv =3D cpu_to_le32(irq + 3); + smmu->flags =3D 0x1; /* COHACC Override */ + + /* Identity RID mapping covering the whole input RID range */ + idmap =3D &smmu->id_mapping_array[0]; + idmap->input_base =3D 0; + idmap->id_count =3D cpu_to_le32(0xFFFF); + idmap->output_base =3D 0; + /* output IORT node is the ITS group node (the first node) */ + idmap->output_reference =3D cpu_to_le32(iort->node_offset); + } + /* Root Complex Node */ node_size =3D sizeof(*rc) + sizeof(*idmap); iort_length +=3D node_size; @@ -438,8 +476,14 @@ build_iort(GArray *table_data, BIOSLinker *linker) idmap->input_base =3D 0; idmap->id_count =3D cpu_to_le32(0xFFFF); idmap->output_base =3D 0; - /* output IORT node is the ITS group node (the first node) */ - idmap->output_reference =3D cpu_to_le32(iort->node_offset); + + if (vms->smmu_info.type) { + /* output IORT node is the smmuv3 node */ + idmap->output_reference =3D cpu_to_le32(smmu_offset); + } else { + /* output IORT node is the ITS group node (the first node) */ + idmap->output_reference =3D cpu_to_le32(iort->node_offset); + } =20 iort->length =3D cpu_to_le32(iort_length); =20 @@ -782,7 +826,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTa= bles *tables) =20 if (its_class_name() && !vmc->no_its) { acpi_add_table(table_offsets, tables_blob); - build_iort(tables_blob, tables->linker); + build_iort(tables_blob, tables->linker, vms); } =20 /* XSDT is pointed to by RSDP */ diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 72be675..69307b7 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -697,6 +697,21 @@ struct AcpiIortItsGroup { } QEMU_PACKED; typedef struct AcpiIortItsGroup AcpiIortItsGroup; =20 +struct AcpiIortSmmu3 { + ACPI_IORT_NODE_HEADER_DEF + uint64_t base_address; + uint32_t flags; + uint32_t reserved2; + uint64_t vatos_address; + uint32_t model; + uint32_t event_gsiv; + uint32_t pri_gsiv; + uint32_t gerr_gsiv; + uint32_t sync_gsiv; + AcpiIortIdMapping id_mapping_array[0]; +} QEMU_PACKED; +typedef struct AcpiIortSmmu3 AcpiIortSmmu3; + struct AcpiIortRC { ACPI_IORT_NODE_HEADER_DEF AcpiIortMemoryAccess memory_properties; diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index ae2bf2c..fd6f34f 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -87,6 +87,18 @@ typedef struct { bool claim_edge_triggered_timers; } VirtMachineClass; =20 +typedef enum VirtIOMMUType { + VIRT_IOMMU_NONE, + VIRT_IOMMU_SMMUV3, + VIRT_IOMMU_VIRTIO, +} VirtIOMMUType; + +typedef struct VirtIOMMUInfo { + VirtIOMMUType type; + MemMapEntry reg; + int irq_base; +} VirtIOMMUInfo; + typedef struct { MachineState parent; Notifier machine_done; @@ -95,6 +107,7 @@ typedef struct { bool highmem; bool its; bool virt; + VirtIOMMUInfo smmu_info; int32_t gic_version; struct arm_boot_info bootinfo; const MemMapEntry *memmap; --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287346271294.56255923072683; Fri, 1 Sep 2017 10:35:46 -0700 (PDT) Received: from localhost ([::1]:51522 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpr7-000105-7y for importer@patchew.org; Fri, 01 Sep 2017 13:35:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38220) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpgd-0007Jh-E6 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpgY-0004c2-P9 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:24:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57970) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpgS-0004VL-E0; Fri, 01 Sep 2017 13:24:44 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 61A6661487; Fri, 1 Sep 2017 17:24:43 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2F99F17100; Fri, 1 Sep 2017 17:24:36 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 61A6661487 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=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:22 +0200 Message-Id: <1504286483-23327-20-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 01 Sep 2017 17:24:43 +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] [PATCH v7 19/20] hw/arm/smmuv3: [not for upstream] add SMMU_CMD_TLBI_NH_VA_AM handling 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, wtownsen@redhat.com 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" SMMUV3 does not support any IOVA range TLBI command: SMMU_CMD_TLBI_NH_VA invalidates TLB entries by page. That's an issue when running DPDK on guest. DPDK uses hugepages but each time a hugepage is mapped on guest side, a storm of SMMU_CMD_TLBI_NH_VA commands get sent by the guest smmuv3 driver and trapped by QEMU for VFIO replay. Let's get prepared to handle implementation defined commands, SMMU_CMD_TLBI_NH_VA_VM, which invalidate a range of IOVAs. Upon this command, we notify the whole range in one host. Signed-off-by: Eric Auger --- hw/arm/smmuv3-internal.h | 1 + hw/arm/smmuv3.c | 13 +++++++++++++ hw/arm/trace-events | 1 + 3 files changed, 15 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index f9f95ae..e70cf76 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -289,6 +289,7 @@ enum { SMMU_CMD_RESUME =3D 0x44, SMMU_CMD_STALL_TERM, SMMU_CMD_SYNC, /* 0x46 */ + SMMU_CMD_TLBI_NH_VA_AM =3D 0x8F, /* VIOMMU Impl Defined */ }; =20 static const char *cmd_stringify[] =3D { diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 9c8640f..55dc80b 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -880,6 +880,19 @@ static int smmuv3_cmdq_consume(SMMUV3State *s) smmuv3_replay_iova_range(&s->smmu_state, addr, size); break; } + case SMMU_CMD_TLBI_NH_VA_AM: + { + int asid =3D extract32(cmd.word[1], 16, 16); + int am =3D extract32(cmd.word[1], 0, 16); + uint64_t low =3D extract32(cmd.word[2], 12, 20); + uint64_t high =3D cmd.word[3]; + uint64_t addr =3D high << 32 | (low << 12); + size_t size =3D am << 12; + + trace_smmuv3_cmdq_tlbi_nh_va_am(asid, am, addr, size); + smmuv3_replay_iova_range(&s->smmu_state, addr, size); + break; + } case SMMU_CMD_TLBI_NH_VAA: case SMMU_CMD_TLBI_EL3_ALL: case SMMU_CMD_TLBI_EL3_VA: diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 15f84d6..fba33ac 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -26,6 +26,7 @@ smmuv3_cmdq_opcode(const char *opcode) "<--- %s" smmuv3_cmdq_cfgi_ste(int streamid) " |_ streamid =3D%d" smmuv3_cmdq_cfgi_ste_range(int start, int end) " |_ start=3D0x%d - end= =3D0x%d" smmuv3_cmdq_tlbi_nh_va(int asid, int vmid, uint64_t addr) " |_ asid = =3D%d vmid =3D%d addr=3D0x%"PRIx64 +smmuv3_cmdq_tlbi_nh_va_am(int asid, int am, size_t size, uint64_t addr) " = |_ asid =3D%d am =3D%d size=3D0x%lx addr=3D0x%"PRIx64 smmuv3_cmdq_consume_out(uint8_t prod_wrap, uint32_t prod, uint8_t cons_wra= p, uint32_t cons) "prod_wrap:%d, prod:0x%x cons_wrap:%d cons:0x%x" smmuv3_update(bool is_empty, uint32_t prod, uint32_t cons, uint8_t prod_wr= ap, uint8_t cons_wrap) "q empty:%d prod:%d cons:%d p.wrap:%d p.cons:%d" smmuv3_update_check_cmd(int error) "cmdq not enabled or error :0x%x" --=20 2.5.5 From nobody Sun Apr 28 12:04:37 2024 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 1504287488938536.2443541655948; Fri, 1 Sep 2017 10:38:08 -0700 (PDT) Received: from localhost ([::1]:51597 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnptP-0003Sa-Fv for importer@patchew.org; Fri, 01 Sep 2017 13:38:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38373) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dnpgr-0007ZK-U9 for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:25:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dnpgn-0004qW-Mt for qemu-devel@nongnu.org; Fri, 01 Sep 2017 13:25:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:52436) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dnpgc-0004fU-TX; Fri, 01 Sep 2017 13:24:55 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E879A81DF5; Fri, 1 Sep 2017 17:24:53 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-241.ams2.redhat.com [10.36.117.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id B93D7627DE; Fri, 1 Sep 2017 17:24:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E879A81DF5 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=eric.auger@redhat.com 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, prem.mallappa@gmail.com, alex.williamson@redhat.com Date: Fri, 1 Sep 2017 19:21:23 +0200 Message-Id: <1504286483-23327-21-git-send-email-eric.auger@redhat.com> In-Reply-To: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> References: <1504286483-23327-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 01 Sep 2017 17:24:54 +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] [PATCH v7 20/20] hw/arm/smmuv3: [not for upstream] Add caching-mode option 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, wtownsen@redhat.com 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" In VFIO use cases, the virtual smmu translates IOVA->IPA (stage 1) whereas the physical SMMU translates IPA -> host PA (stage 2). The 2 stages of the physical SMMU are currently not used. Instead both stage 1 and stage2 mappings are combined together and programmed in a single stage (S1) in the physical SMMU. The drawback of this approach is each time the IOVA->IPA mapping is changed by the guest, the host must be notified to re-program the physical SMMU with the combined stages. So we need to trap into the QEMU device each time the guest alters the configuration or TLB data. Unfortunately the SMMU does not expose any caching mode as the Intel IOMMU. On Intel, this caching mode HW bit informs the OS that each time it updates the remapping structures (even on map) it must invalidate the caches. Those invalidate commands are used to notify the host that it must recompute S1+S2 mappings and reprogram the HW. As we don't have the HW bit on ARM, we currently rely on a a FW quirk on guest smmuv3 driver side. When this FW quirk is applied the driver performs TLB invalidations on map and sends SMMU_CMD_TLBI_NH_VA_AM commands. Those TLB invalidations are used to trap changes in the translation tables. We introduced a new implemented defined SMMU_CMD_TLBI_NH_VA_AM command since it allows to inavlidate a whole range instead of invalidating a single page (native SMMU_CMD_TLBI_NH_VA command). As a consequence anybody wanting to use virtual smmuv3 in VFIO use case must add -device smmuv3,caching-mode to the option line. Signed-off-by: Eric Auger --- hw/arm/smmuv3.c | 7 +++++++ hw/arm/sysbus-fdt.c | 11 ++++++++++- hw/arm/virt-acpi-build.c | 7 ++++++- include/hw/arm/smmuv3.h | 1 + include/hw/arm/virt.h | 1 + 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 55dc80b..bb35e50 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1122,6 +1122,12 @@ static const VMStateDescription vmstate_smmuv3 =3D { }, }; =20 +static Property smmuv3_dev_properties[] =3D { + DEFINE_PROP_BOOL("caching-mode", SMMUV3State, cm, false), + DEFINE_PROP_END_OF_LIST(), +}; + + static void smmuv3_instance_init(Object *obj) { /* Nothing much to do here as of now */ @@ -1131,6 +1137,7 @@ static void smmuv3_class_init(ObjectClass *klass, voi= d *data) { DeviceClass *dc =3D DEVICE_CLASS(klass); =20 + dc->props =3D smmuv3_dev_properties; dc->reset =3D smmu_reset; dc->vmsd =3D &vmstate_smmuv3; dc->realize =3D smmu_realize; diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c index 4583acf..cfb40a4 100644 --- a/hw/arm/sysbus-fdt.c +++ b/hw/arm/sysbus-fdt.c @@ -440,6 +440,7 @@ static int add_smmuv3_fdt_node(SysBusDevice *sbdev, voi= d *opaque) const char *parent_node =3D data->pbus_node_name; PlatformBusDevice *pbus =3D data->pbus; VirtMachineState *vms =3D data->vms; + SMMUV3State *smmu =3D SMMU_V3_DEV(sbdev); void *guest_fdt =3D data->fdt; char *nodename, *node_path; int i; @@ -471,6 +472,10 @@ static int add_smmuv3_fdt_node(SysBusDevice *sbdev, vo= id *opaque) qemu_fdt_setprop_string(guest_fdt, nodename, "clock-names", "apb_pclk"= ); qemu_fdt_setprop(guest_fdt, nodename, "dma-coherent", NULL, 0); =20 + if (smmu->cm) { + qemu_fdt_setprop(guest_fdt, nodename, "tlbi-on-map", NULL, 0); + } + qemu_fdt_setprop_cell(guest_fdt, nodename, "#iommu-cells", 1); =20 smmu_phandle =3D qemu_fdt_alloc_phandle(vms->fdt); @@ -487,7 +492,11 @@ static int add_smmuv3_fdt_node(SysBusDevice *sbdev, vo= id *opaque) qemu_fdt_setprop_cells(guest_fdt, node_path, "iommu-map", 0x0, smmu_phandle, 0x0, 0x10000); =20 - vms->smmu_info.type =3D VIRT_IOMMU_SMMUV3; + if (smmu->cm) { + vms->smmu_info.type =3D VIRT_IOMMU_SMMUV3_CACHING_MODE; + } else { + vms->smmu_info.type =3D VIRT_IOMMU_SMMUV3; + } vms->smmu_info.reg.base =3D data->base + mmio_base; vms->smmu_info.reg.size =3D 0x20000; vms->smmu_info.irq_base =3D irq_number; diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 8395898..cc10e79 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -426,7 +426,8 @@ build_iort(GArray *table_data, BIOSLinker *linker, Virt= MachineState *vms) its->its_count =3D cpu_to_le32(1); its->identifiers[0] =3D 0; /* MADT translation_id */ =20 - if (vms->smmu_info.type =3D=3D VIRT_IOMMU_SMMUV3) { + if (vms->smmu_info.type =3D=3D VIRT_IOMMU_SMMUV3 || + vms->smmu_info.type =3D=3D VIRT_IOMMU_SMMUV3_CACHING_MODE) { int irq =3D vms->smmu_info.irq_base; =20 /* SMMUv3 node */ @@ -438,6 +439,10 @@ build_iort(GArray *table_data, BIOSLinker *linker, Vir= tMachineState *vms) =20 smmu->type =3D ACPI_IORT_NODE_SMMU_V3; smmu->length =3D cpu_to_le16(node_size); + + if (vms->smmu_info.type =3D=3D VIRT_IOMMU_SMMUV3_CACHING_MODE) { + smmu->model =3D 0x3; /* ACPI_IORT_SMMU_V3_CACHING_MODE */ + } smmu->mapping_count =3D cpu_to_le32(1); smmu->mapping_offset =3D cpu_to_le32(sizeof(*smmu)); smmu->base_address =3D cpu_to_le64(vms->smmu_info.reg.base); diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h index 0c8973d..16ae5c6 100644 --- a/include/hw/arm/smmuv3.h +++ b/include/hw/arm/smmuv3.h @@ -58,6 +58,7 @@ typedef struct SMMUV3State { qemu_irq irq[4]; SMMUQueue cmdq, evtq; =20 + bool cm; /* caching mode */ } SMMUV3State; =20 typedef enum { diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index fd6f34f..7669a7c 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -90,6 +90,7 @@ typedef struct { typedef enum VirtIOMMUType { VIRT_IOMMU_NONE, VIRT_IOMMU_SMMUV3, + VIRT_IOMMU_SMMUV3_CACHING_MODE, VIRT_IOMMU_VIRTIO, } VirtIOMMUType; =20 --=20 2.5.5