From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518895283356171.8180731172382; Sat, 17 Feb 2018 11:21:23 -0800 (PST) Received: from localhost ([::1]:49491 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en830-0008EN-86 for importer@patchew.org; Sat, 17 Feb 2018 14:21:22 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44832) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7W5-0003Im-7I for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7W3-0000yJ-4B for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:21 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:43716 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7Vv-0000Ly-46; Sat, 17 Feb 2018 13:47:11 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E37DD8424C; Sat, 17 Feb 2018 18:47:08 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 504542024CA2; Sat, 17 Feb 2018 18:47:06 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:43 +0100 Message-Id: <1518893216-9983-2-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 17 Feb 2018 18:47:09 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 17 Feb 2018 18:47:09 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 01/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Peter Maydell --- v8 -> v9: - remove page walk callback type from this patch (vhost related) - add a new hash table for caching configuration data - add reset function - add asid v7 -> v8: - add bus_num property - add primary-bus property - add realize and remove instance_init - rename TYPE and related macros to match naming convention using for GIC - add SMMUPageTableWalkEventInfo - tt[2] in translation config 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 Conflicts: default-configs/aarch64-softmmu.mak --- default-configs/aarch64-softmmu.mak | 1 + hw/arm/Makefile.objs | 1 + hw/arm/smmu-common.c | 80 +++++++++++++++++++++++ include/hw/arm/smmu-common.h | 124 ++++++++++++++++++++++++++++++++= ++++ 4 files changed, 206 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 9ddccf8..6f790f0 100644 --- a/default-configs/aarch64-softmmu.mak +++ b/default-configs/aarch64-softmmu.mak @@ -8,3 +8,4 @@ CONFIG_DDC=3Dy CONFIG_DPCD=3Dy CONFIG_XLNX_ZYNQMP=3Dy CONFIG_XLNX_ZYNQMP_ARM=3Dy +CONFIG_ARM_SMMUV3=3Dy diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 1c896ba..c84c5ac 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -20,3 +20,4 @@ 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_MSF2) +=3D msf2-soc.o msf2-som.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..86a5aab --- /dev/null +++ b/hw/arm/smmu-common.c @@ -0,0 +1,80 @@ +/* + * 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. + * + * 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 "hw/qdev-properties.h" +#include "qapi/error.h" + +#include "qemu/error-report.h" +#include "hw/arm/smmu-common.h" + +static void smmu_base_realize(DeviceState *dev, Error **errp) +{ + SMMUState *s =3D ARM_SMMU(dev); + + s->configs =3D g_hash_table_new_full(NULL, NULL, NULL, g_free); + s->iotlb =3D g_hash_table_new_full(NULL, NULL, NULL, g_free); +} + +static void smmu_base_reset(DeviceState *dev) +{ + SMMUState *s =3D ARM_SMMU(dev); + + g_hash_table_remove_all(s->configs); + g_hash_table_remove_all(s->iotlb); +} + +static Property smmu_dev_properties[] =3D { + DEFINE_PROP_UINT8("bus_num", SMMUState, bus_num, 0), + DEFINE_PROP_LINK("primary-bus", SMMUState, primary_bus, "PCI", PCIBus = *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void smmu_base_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + SMMUBaseClass *sbc =3D ARM_SMMU_CLASS(klass); + + dc->props =3D smmu_dev_properties; + sbc->parent_realize =3D dc->realize; + dc->realize =3D smmu_base_realize; + dc->reset =3D smmu_base_reset; +} + +static const TypeInfo smmu_base_info =3D { + .name =3D TYPE_ARM_SMMU, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(SMMUState), + .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..8a9d931 --- /dev/null +++ b/include/hw/arm/smmu-common.h @@ -0,0 +1,124 @@ +/* + * 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 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. + * + */ + +#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 + +#define SMMU_MAX_VA_BITS 48 + +/* + * Page table walk error types + */ +typedef enum { + SMMU_PTW_ERR_NONE, + SMMU_PTW_ERR_WALK_EABT, /* Translation walk external abort */ + SMMU_PTW_ERR_TRANSLATION, /* Translation fault */ + SMMU_PTW_ERR_ADDR_SIZE, /* Address Size fault */ + SMMU_PTW_ERR_ACCESS, /* Access fault */ + SMMU_PTW_ERR_PERMISSION, /* Permission fault */ +} SMMUPTWEventType; + +typedef struct SMMUPTWEventInfo { + SMMUPTWEventType type; + dma_addr_t addr; /* fetched address that induced an abort, if any */ +} SMMUPTWEventInfo; + +typedef struct SMMUTransTableInfo { + bool disabled; /* is the translation table disabled? */ + uint64_t ttb; /* TT base address */ + uint8_t tsz; /* input range, ie. 2^(64 -tsz)*/ + uint8_t granule_sz; /* granule page shift */ + uint8_t initial_level; /* initial lookup level */ +} SMMUTransTableInfo; + +/* + * Generic structure populated by derived SMMU devices + * after decoding the configuration information and used as + * input to the page table walk + */ +typedef struct SMMUTransCfg { + int stage; /* translation stage */ + bool aa64; /* arch64 or aarch32 translation table */ + bool disabled; /* smmu is disabled */ + bool bypassed; /* translation is bypassed */ + bool aborted; /* translation is aborted */ + uint64_t ttb; /* TT base address */ + uint8_t oas; /* output address width */ + uint8_t tbi; /* Top Byte Ignore */ + uint16_t asid; + SMMUTransTableInfo tt[2]; +} 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; + GHashTable *configs; /* cache for configuration data */ + GHashTable *iotlb; + SMMUPciBus *smmu_as_by_bus_num[SMMU_PCI_BUS_MAX]; + PCIBus *pci_bus; + QLIST_HEAD(, SMMUNotifierNode) notifiers_list; + uint8_t bus_num; + PCIBus *primary_bus; +} SMMUState; + +typedef struct { + /* */ + SysBusDeviceClass parent_class; + + /*< public >*/ + + DeviceRealize parent_realize; + +} SMMUBaseClass; + +#define TYPE_ARM_SMMU "arm-smmu" +#define ARM_SMMU(obj) OBJECT_CHECK(SMMUState, (obj), TYPE_ARM_SMMU) +#define ARM_SMMU_CLASS(klass) \ + OBJECT_CLASS_CHECK(SMMUBaseClass, (klass), TYPE_ARM_SMMU) +#define ARM_SMMU_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU) + +#endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518896014189714.2254738586369; Sat, 17 Feb 2018 11:33:34 -0800 (PST) Received: from localhost ([::1]:51588 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8En-0003TW-74 for importer@patchew.org; Sat, 17 Feb 2018 14:33:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44829) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7W4-0003IP-Rh for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:22 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7W3-0000yW-4K for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:20 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52358 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7Vw-0000UE-Ap; Sat, 17 Feb 2018 13:47:12 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C07EE402242D; Sat, 17 Feb 2018 18:47:11 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 30C312024CA2; Sat, 17 Feb 2018 18:47:09 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:44 +0100 Message-Id: <1518893216-9983-3-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 17 Feb 2018 18:47:11 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 17 Feb 2018 18:47:11 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 02/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 --- v8 -> v9: - fix key value for lookup v7 -> v8: - introduce SMMU_MAX_VA_BITS - use PCI bus handle as a key - do not clear s->smmu_as_by_bus_num - use g_new0 instead of g_malloc0 - use primary_bus field --- hw/arm/smmu-common.c | 59 ++++++++++++++++++++++++++++++++++++++++= ++++ include/hw/arm/smmu-common.h | 6 +++++ 2 files changed, 65 insertions(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 86a5aab..d0516dc 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -28,12 +28,71 @@ #include "qemu/error-report.h" #include "hw/arm/smmu-common.h" =20 +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; + SMMUPciBus *sbus =3D g_hash_table_lookup(s->smmu_as_by_busptr, bus); + SMMUDevice *sdev; + + if (!sbus) { + 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, bus, 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_new0(SMMUDevice, 1); + + 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 << SMMU_MAX_VA_BITS= ); + address_space_init(&sdev->as, + MEMORY_REGION(&sdev->iommu), name); + } + + return &sdev->as; +} + static void smmu_base_realize(DeviceState *dev, Error **errp) { SMMUState *s =3D ARM_SMMU(dev); =20 s->configs =3D g_hash_table_new_full(NULL, NULL, NULL, g_free); s->iotlb =3D g_hash_table_new_full(NULL, NULL, NULL, g_free); + s->smmu_as_by_busptr =3D g_hash_table_new(NULL, NULL); + + if (s->primary_bus) { + pci_setup_iommu(s->primary_bus, smmu_find_add_as, s); + } else { + error_setg(errp, "SMMU is not attached to any PCI bus!"); + } } =20 static void smmu_base_reset(DeviceState *dev) diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 8a9d931..aee96c2 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -121,4 +121,10 @@ typedef struct { #define ARM_SMMU_GET_CLASS(obj) \ OBJECT_GET_CLASS(SMMUBaseClass, (obj), TYPE_ARM_SMMU) =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 Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518895322816579.106306091416; Sat, 17 Feb 2018 11:22:02 -0800 (PST) Received: from localhost ([::1]:49493 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en83d-0000ME-Q3 for importer@patchew.org; Sat, 17 Feb 2018 14:22:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44869) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7W7-0003L0-G6 for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7W4-000168-Rq for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:23 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36078 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7Vz-0000gi-Ay; Sat, 17 Feb 2018 13:47:15 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C6821EAE83; Sat, 17 Feb 2018 18:47:14 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 108CF2024CA2; Sat, 17 Feb 2018 18:47:11 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:45 +0100 Message-Id: <1518893216-9983-4-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 17 Feb 2018 18:47:14 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 17 Feb 2018 18:47:14 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 03/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch implements the page table walk for VMSAv8-64. Signed-off-by: Eric Auger --- v8 -> v9: - remove guest error log on PTE fetch fault - rename trace functions - fix smmu_page_walk_level_res_invalid_pte last arg - fix PTE_ADDRESS - turn functions into macros - make sure to return the actual pte access permission into tlbe->perm - change proto of smmu_ptw* v7 -> v8: - rework get_pte - use LOG_LEVEL_ERROR - remove error checking in get_block_pte_address - page table walk simplified (no VFIO replay anymore) - handle PTW error events - use dma_memory_read 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 | 232 +++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/smmu-internal.h | 96 ++++++++++++++++++ hw/arm/trace-events | 10 ++ include/hw/arm/smmu-common.h | 6 ++ 4 files changed, 344 insertions(+) create mode 100644 hw/arm/smmu-internal.h diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index d0516dc..24cc4ba 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -27,6 +27,238 @@ =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 t + * @base_addr[@index] + */ +static int get_pte(dma_addr_t baseaddr, uint32_t index, uint64_t *pte, + SMMUPTWEventInfo *info) +{ + int ret; + dma_addr_t addr =3D baseaddr + index * sizeof(*pte); + + ret =3D dma_memory_read(&address_space_memory, addr, + (uint8_t *)pte, sizeof(*pte)); + + if (ret !=3D MEMTX_OK) { + info->type =3D SMMU_PTW_ERR_WALK_EABT; + info->addr =3D addr; + return -EINVAL; + } + trace_smmu_get_pte(baseaddr, index, addr, *pte); + return 0; +} + +/* VMSAv8-64 Translation Table Format Descriptor Decoding */ + +/** + * 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 =3D 0; + + switch (granule_sz) { + case 12: + if (level =3D=3D 1) { + n =3D 30; + } else if (level =3D=3D 2) { + n =3D 21; + } + break; + case 14: + if (level =3D=3D 2) { + n =3D 25; + } + break; + case 16: + if (level =3D=3D 2) { + n =3D 29; + } + break; + } + if (!n) { + error_setg(&error_fatal, + "wrong granule/level combination (%d/%d)", + granule_sz, level); + } + *bsz =3D 1 << n; + return PTE_ADDRESS(pte, n); +} + +static inline bool check_perm(int access_attrs, int mem_attrs) +{ + if (((access_attrs & IOMMU_RO) && !(mem_attrs & IOMMU_RO)) || + ((access_attrs & IOMMU_WO) && !(mem_attrs & IOMMU_WO))) { + return false; + } + return true; +} + +SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova) +{ + if (!extract64(iova, 64 - cfg->tt[0].tsz, cfg->tt[0].tsz - cfg->tbi)) { + return &cfg->tt[0]; + } + return &cfg->tt[1]; +} + +/** + * smmu_ptw_64 - VMSAv8-64 Walk of the page tables for a given IOVA + * @cfg: translation config + * @iova: iova to translate + * @perm: access type + * @tlbe: IOMMUTLBEntry (out) + * @info: handle to an error info + * + * Return 0 on success, < 0 on error. In case of error, @info is filled + * and tlbe->perm is set to IOMMU_NONE. + * Upon success, @tlbe is filled with translated_addr and entry + * permission rights. + */ +static int smmu_ptw_64(SMMUTransCfg *cfg, + dma_addr_t iova, IOMMUAccessFlags perm, + IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) +{ + dma_addr_t baseaddr; + int stage =3D cfg->stage; + SMMUTransTableInfo *tt =3D select_tt(cfg, iova); + uint8_t level; + uint8_t granule_sz; + + if (tt->disabled) { + info->type =3D SMMU_PTW_ERR_TRANSLATION; + goto error; + } + + level =3D tt->initial_level; + granule_sz =3D tt->granule_sz; + baseaddr =3D extract64(tt->ttb, 0, 48); + + tlbe->iova =3D iova; + tlbe->addr_mask =3D (1 << tt->granule_sz) - 1; + + while (level <=3D 3) { + uint64_t subpage_size =3D 1ULL << level_shift(level, granule_sz); + uint64_t mask =3D subpage_size - 1; + uint32_t offset =3D iova_level_offset(iova, level, granule_sz); + uint64_t pte; + dma_addr_t pte_addr =3D baseaddr + offset * sizeof(pte); + uint8_t ap; + + if (get_pte(baseaddr, offset, &pte, info)) { + goto error; + } + trace_smmu_ptw_level(level, iova, subpage_size, + baseaddr, offset, pte); + + if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) { + trace_smmu_ptw_invalid_pte(stage, level, baseaddr, + pte_addr, offset, pte); + info->type =3D SMMU_PTW_ERR_TRANSLATION; + goto error; + } + + if (is_page_pte(pte, level)) { + uint64_t gpa =3D get_page_pte_address(pte, granule_sz); + + ap =3D PTE_AP(pte); + if (is_permission_fault(ap, perm)) { + info->type =3D SMMU_PTW_ERR_PERMISSION; + goto error; + } + + tlbe->translated_addr =3D gpa + (iova & mask); + tlbe->perm =3D PTE_AP_TO_PERM(ap); + trace_smmu_ptw_page_pte(stage, level, iova, + baseaddr, pte_addr, pte, gpa); + return 0; + } + if (is_block_pte(pte, level)) { + uint64_t block_size; + hwaddr gpa =3D get_block_pte_address(pte, level, granule_sz, + &block_size); + + ap =3D PTE_AP(pte); + if (is_permission_fault(ap, perm)) { + info->type =3D SMMU_PTW_ERR_PERMISSION; + goto error; + } + + trace_smmu_ptw_block_pte(stage, level, baseaddr, + pte_addr, pte, iova, gpa, + (int)(block_size >> 20)); + + tlbe->translated_addr =3D gpa + (iova & mask); + tlbe->perm =3D PTE_AP_TO_PERM(ap); + return 0; + } + + /* table pte */ + ap =3D PTE_APTABLE(pte); + + if (is_permission_fault(ap, perm)) { + info->type =3D SMMU_PTW_ERR_PERMISSION; + goto error; + } + baseaddr =3D get_table_pte_address(pte, granule_sz); + level++; + } + + info->type =3D SMMU_PTW_ERR_TRANSLATION; + +error: + tlbe->perm =3D IOMMU_NONE; + return -EINVAL; +} + +/** + * smmu_ptw - Walk the page tables for an IOVA, according to @cfg + * + * @cfg: translation configuration + * @iova: iova to translate + * @perm: tentative access type + * @tlbe: returned entry + * @info: ptw event handle + * + * return 0 on success + */ +int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, + IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info) +{ + if (!cfg->aa64) { + error_setg(&error_fatal, + "SMMUv3 model does not support VMSAv8-32 page walk yet"= ); + } + + return smmu_ptw_64(cfg, iova, perm, tlbe, info); +} =20 SMMUPciBus *smmu_find_as_from_bus_num(SMMUState *s, uint8_t bus_num) { diff --git a/hw/arm/smmu-internal.h b/hw/arm/smmu-internal.h new file mode 100644 index 0000000..3ed97ee --- /dev/null +++ b/hw/arm/smmu-internal.h @@ -0,0 +1,96 @@ +/* + * ARM SMMU support - Internal API + * + * Copyright (c) 2017 Red Hat, Inc. + * Copyright (C) 2014-2016 Broadcom Corporation + * 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 + * 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_TABLE 3 + +#define ARM_LPAE_L3_PTE_TYPE_RESERVED 1 +#define ARM_LPAE_L3_PTE_TYPE_PAGE 3 + +#define ARM_LPAE_PTE_VALID (1 << 0) + +#define PTE_ADDRESS(pte, shift) \ + (extract64(pte, shift, 47 - shift + 1) << shift) + +#define is_invalid_pte(pte) (!(pte & ARM_LPAE_PTE_VALID)) + +#define is_reserved_pte(pte, level) \ + ((level =3D=3D 3) && = \ + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_L3_PTE_TYPE_RESERVED)) + +#define is_block_pte(pte, level) \ + ((level < 3) && \ + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_BLOCK)) + +#define is_table_pte(pte, level) \ + ((level < 3) && \ + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_TABLE)) + +#define is_page_pte(pte, level) \ + ((level =3D=3D 3) && = \ + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_L3_PTE_TYPE_PAGE)) + +#define PTE_AP(pte) \ + (extract64(pte, 6, 2)) + +#define PTE_APTABLE(pte) \ + (extract64(pte, 61, 2)) + +#define is_permission_fault(ap, perm) \ + (((perm) & IOMMU_WO) && ((ap) & 0x2)) + +#define PTE_AP_TO_PERM(ap) \ + (IOMMU_ACCESS_FLAG(true, !((ap) & 0x2))) + +/* 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..3584974 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -2,3 +2,13 @@ =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_lookup_table(int level, uint64_t baseaddr, int granule_sz, uint64_t s= tart, uint64_t end, int flags, uint64_t subpage_size) "level=3D%d baseaddr= =3D0x%"PRIx64" granule=3D%d, start=3D0x%"PRIx64" end=3D0x%"PRIx64" flags=3D= %d subpage_size=3D0x%lx" +smmu_ptw_level(int level, uint64_t iova, size_t subpage_size, uint64_t bas= eaddr, uint32_t offset, uint64_t pte) "level=3D%d iova=3D0x%lx subpage_sz= =3D0x%lx baseaddr=3D0x%"PRIx64" offset=3D%d =3D> pte=3D0x%lx" +smmu_ptw_invalid_pte(int stage, int level, uint64_t baseaddr, uint64_t pte= addr, uint32_t offset, uint64_t pte) "stage=3D%d level=3D%d base@=3D0x%"PRI= x64" pte@=3D0x%"PRIx64" offset=3D%d pte=3D0x%"PRIx64 +smmu_ptw_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 i= ova=3D0x%"PRIx64" base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" = page address =3D 0x%"PRIx64 +smmu_ptw_block_pte(int stage, int level, uint64_t baseaddr, uint64_t ptead= dr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "stage=3D%d le= vel=3D%d base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" iova=3D0x= %"PRIx64" block address =3D 0x%"PRIx64" block size =3D %d MiB" +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 diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index aee96c2..0fb27f7 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -127,4 +127,10 @@ static inline uint16_t smmu_get_sid(SMMUDevice *sdev) { return ((pci_bus_num(sdev->bus) & 0xff) << 8) | sdev->devfn; } + +int smmu_ptw(SMMUTransCfg *cfg, dma_addr_t iova, IOMMUAccessFlags perm, + IOMMUTLBEntry *tlbe, SMMUPTWEventInfo *info); + +SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova); + #endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 151889681274863.958652708726504; Sat, 17 Feb 2018 11:46:52 -0800 (PST) Received: from localhost ([::1]:54510 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8Rf-0008BV-QL for importer@patchew.org; Sat, 17 Feb 2018 14:46:51 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45012) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WG-0003V4-TN for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WC-0001dp-4n for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:32 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:56726 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7W2-0000tF-Aw; Sat, 17 Feb 2018 13:47:18 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B8C138182D06; Sat, 17 Feb 2018 18:47:17 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 15C002024CA2; Sat, 17 Feb 2018 18:47:14 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:46 +0100 Message-Id: <1518893216-9983-5-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 17 Feb 2018 18:47:17 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 17 Feb 2018 18:47:17 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 04/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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. Only the MMIO read operation is implemented here. Signed-off-by: Prem Mallappa Signed-off-by: Eric Auger --- v8 -> v9: - add #include "qemu/log.h" - add parent_reset v7 -> v8: - remove __smmu_data structs - revisit struct SMMUQueue - do not advertise stage 2 support anymore - use the register definition API and get rid of REG array - get read of queue structs 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 | 155 +++++++++++++++++++++ hw/arm/smmuv3.c | 348 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 3 + include/hw/arm/smmuv3.h | 91 +++++++++++++ 5 files changed, 598 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 c84c5ac..676b222 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -20,4 +20,4 @@ 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_MSF2) +=3D msf2-soc.o msf2-som.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..5be8303 --- /dev/null +++ b/hw/arm/smmuv3-internal.h @@ -0,0 +1,155 @@ +/* + * 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 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, see . + */ + +#ifndef HW_ARM_SMMU_V3_INTERNAL_H +#define HW_ARM_SMMU_V3_INTERNAL_H + +#include "qemu/log.h" +#include "trace.h" +#include "qemu/error-report.h" +#include "hw/arm/smmu-common.h" + +/* MMIO Registers */ + +REG32(IDR0, 0x0) + FIELD(IDR0, S1P, 1 , 1) + FIELD(IDR0, TTF, 2 , 2) + FIELD(IDR0, COHACC, 4 , 1) + FIELD(IDR0, ASID16, 12, 1) + FIELD(IDR0, TTENDIAN, 21, 2) + FIELD(IDR0, STALL_MODEL, 24, 2) + FIELD(IDR0, TERM_MODEL, 26, 1) + FIELD(IDR0, STLEVEL, 27, 2) + +REG32(IDR1, 0x4) + FIELD(IDR1, SIDSIZE, 0 , 6) + FIELD(IDR1, EVENTQS, 16, 5) + FIELD(IDR1, CMDQS, 21, 5) + +#define SMMU_IDR1_SIDSIZE 16 + +REG32(IDR2, 0x8) +REG32(IDR3, 0xc) +REG32(IDR4, 0x10) +REG32(IDR5, 0x14) + FIELD(IDR5, OAS, 0, 3); + FIELD(IDR5, GRAN4K, 4, 1); + FIELD(IDR5, GRAN16K, 5, 1); + FIELD(IDR5, GRAN64K, 6, 1); + +#define SMMU_IDR5_OAS 4 + +REG32(IIDR, 0x1c) +REG32(CR0, 0x20) + FIELD(CR0, SMMU_ENABLE, 0, 1) + FIELD(CR0, EVENTQEN, 2, 1) + FIELD(CR0, CMDQEN, 3, 1) + +REG32(CR0ACK, 0x24) +REG32(CR1, 0x28) +REG32(CR2, 0x2c) +REG32(STATUSR, 0x40) +REG32(IRQ_CTRL, 0x50) + FIELD(IRQ_CTRL, GERROR_IRQEN, 0, 1) + FIELD(IRQ_CTRL, PRI_IRQEN, 1, 1) + FIELD(IRQ_CTRL, EVENTQ_IRQEN, 2, 1) + +REG32(IRQ_CTRL_ACK, 0x54) +REG32(GERROR, 0x60) + FIELD(GERROR, CMDQ_ERR, 0, 1) + FIELD(GERROR, EVENTQ_ABT_ERR, 2, 1) + FIELD(GERROR, PRIQ_ABT_ERR, 3, 1) + FIELD(GERROR, MSI_CMDQ_ABT_ERR, 4, 1) + FIELD(GERROR, MSI_EVENTQ_ABT_ERR, 5, 1) + FIELD(GERROR, MSI_PRIQ_ABT_ERR, 6, 1) + FIELD(GERROR, MSI_GERROR_ABT_ERR, 7, 1) + FIELD(GERROR, MSI_SFM_ERR, 8, 1) + +REG32(GERRORN, 0x64) + +#define A_GERROR_IRQ_CFG0 0x68 /* 64b */ +REG32(GERROR_IRQ_CFG1, 0x70) +REG32(GERROR_IRQ_CFG2, 0x74) + +#define A_STRTAB_BASE 0x80 /* 64b */ + +#define SMMU_BASE_ADDR_MASK 0xffffffffffe0 + +REG32(STRTAB_BASE_CFG, 0x88) + FIELD(STRTAB_BASE_CFG, FMT, 16, 2) + FIELD(STRTAB_BASE_CFG, SPLIT, 6 , 5) + FIELD(STRTAB_BASE_CFG, LOG2SIZE, 0 , 6) + +#define A_CMDQ_BASE 0x90 /* 64b */ +REG32(CMDQ_PROD, 0x98) +REG32(CMDQ_CONS, 0x9c) + FIELD(CMDQ_CONS, ERR, 24, 7) + +#define A_EVENTQ_BASE 0xa0 /* 64b */ +REG32(EVENTQ_PROD, 0xa8) +REG32(EVENTQ_CONS, 0xac) + +#define A_EVENTQ_IRQ_CFG0 0xb0 /* 64b */ +REG32(EVENTQ_IRQ_CFG1, 0xb8) +REG32(EVENTQ_IRQ_CFG2, 0xbc) + +REG32(CIDR0, 0xff0) +REG32(CIDR1, 0xff4) +REG32(CIDR2, 0xff8) +REG32(CIDR3, 0xffc) +REG32(PIDR0, 0xfe0) +REG32(PIDR1, 0xfe4) +REG32(PIDR2, 0xfe8) +REG32(PIDR3, 0xfec) +REG32(PIDR4, 0xfd0) + +static inline int smmu_enabled(SMMUv3State *s) +{ + return FIELD_EX32(s->cr[0], CR0, SMMU_ENABLE); +} + +typedef struct Cmd { + uint32_t word[4]; +} Cmd; + +typedef struct Evt { + uint32_t word[8]; +} Evt; + +static inline uint64_t smmu_read64(uint64_t r, unsigned offset, + unsigned size) +{ + if (size =3D=3D 8 && !offset) { + return r; + } + + /* 32 bit access */ + + if (offset && offset !=3D 4) { + qemu_log_mask(LOG_GUEST_ERROR, + "SMMUv3 MMIO read: bad offset/size %u/%u\n", + offset, size); + return 0; + } + + return extract64(r, offset << 3, 32); +} + +#endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c new file mode 100644 index 0000000..dc03c9e --- /dev/null +++ b/hw/arm/smmuv3.c @@ -0,0 +1,348 @@ +/* + * 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, see . + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "hw/qdev-core.h" +#include "hw/pci/pci.h" +#include "exec/address-spaces.h" +#include "trace.h" +#include "qemu/error-report.h" +#include "qapi/error.h" + +#include "hw/arm/smmuv3.h" +#include "smmuv3-internal.h" + +static void smmuv3_init_regs(SMMUv3State *s) +{ + /** + * IDR0: stage1 only, AArch64 only, coherent access, 16b ASID, + * multi-level stream table + */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, S1P, 1); /* stage 1 supporte= d */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, TTF, 2); /* AArch64 PTW only= */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, COHACC, 1); /* IO coherent */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, ASID16, 1); /* 16-bit ASID */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, TTENDIAN, 2); /* little endi= an */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, STALL_MODEL, 1); /* No stall= */ + /* terminated transaction will always be aborted/error returned */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, TERM_MODEL, 1); + /* 2-level stream table supported */ + s->idr[0] =3D FIELD_DP32(s->idr[0], IDR0, STLEVEL, 1); + + s->idr[1] =3D FIELD_DP32(s->idr[1], IDR1, SIDSIZE, SMMU_IDR1_SIDSIZE); + s->idr[1] =3D FIELD_DP32(s->idr[1], IDR1, EVENTQS, 19); + s->idr[1] =3D FIELD_DP32(s->idr[1], IDR1, CMDQS, 19); + + /* 4K and 64K granule support */ + s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, GRAN4K, 1); + s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, GRAN64K, 1); + s->idr[5] =3D FIELD_DP32(s->idr[5], IDR5, OAS, SMMU_IDR5_OAS); /* 44 b= its */ + + s->cmdq.base =3D deposit64(s->cmdq.base, 0, 5, 19); /* LOG2SIZE =3D 19= */ + s->cmdq.prod =3D 0; + s->cmdq.cons =3D 0; + s->cmdq.entry_size =3D sizeof(struct Cmd); + s->eventq.base =3D deposit64(s->eventq.base, 0, 5, 19); /* LOG2SIZE = =3D 19 */ + s->eventq.prod =3D 0; + s->eventq.cons =3D 0; + s->eventq.entry_size =3D sizeof(struct Evt); + + s->features =3D 0; + s->sid_split =3D 0; +} + +static void smmu_write_mmio(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + /* not yet implemented */ +} + +static uint64_t smmu_read_mmio(void *opaque, hwaddr addr, unsigned size) +{ + SMMUState *sys =3D opaque; + SMMUv3State *s =3D ARM_SMMUV3(sys); + uint64_t val; + + /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ + addr &=3D ~0x10000; + + if (size !=3D 4 && size !=3D 8) { + qemu_log_mask(LOG_GUEST_ERROR, "SMMUv3 MMIO read: bad size %u\n", = size); + return 0; + } + + /* Primecell/Corelink ID registers */ + switch (addr) { + case A_CIDR0: + val =3D 0x0D; + break; + case A_CIDR1: + val =3D 0xF0; + break; + case A_CIDR2: + val =3D 0x05; + break; + case A_CIDR3: + val =3D 0xB1; + break; + case A_PIDR0: + val =3D 0x84; /* Part Number */ + break; + case A_PIDR1: + val =3D 0xB4; /* JEP106 ID code[3:0] for Arm and Part numver[11:8]= */ + break; + case A_PIDR3: + val =3D 0x10; /* MMU600 p1 */ + break; + case A_PIDR4: + val =3D 0x4; /* 4KB region count, JEP106 continuation code for Arm= */ + break; + case 0xFD4 ... 0xFDC: /* SMMU_PDIR 5-7 */ + val =3D 0; + break; + case A_IDR0 ... A_IDR5: + val =3D s->idr[(addr - A_IDR0) / 4]; + break; + case A_IIDR: + val =3D s->iidr; + break; + case A_CR0: + val =3D s->cr[0]; + break; + case A_CR0ACK: + val =3D s->cr0ack; + break; + case A_CR1: + val =3D s->cr[1]; + break; + case A_CR2: + val =3D s->cr[2]; + break; + case A_STATUSR: + val =3D s->statusr; + break; + case A_IRQ_CTRL: + val =3D s->irq_ctrl; + break; + case A_IRQ_CTRL_ACK: + val =3D s->irq_ctrl_ack; + break; + case A_GERROR: + val =3D s->gerror; + break; + case A_GERRORN: + val =3D s->gerrorn; + break; + case A_GERROR_IRQ_CFG0: /* 64b */ + val =3D smmu_read64(s->gerror_irq_cfg0, 0, size); + break; + case A_GERROR_IRQ_CFG0 + 4: + val =3D smmu_read64(s->gerror_irq_cfg0, 4, size); + break; + case A_GERROR_IRQ_CFG1: + val =3D s->gerror_irq_cfg1; + break; + case A_GERROR_IRQ_CFG2: + val =3D s->gerror_irq_cfg2; + break; + case A_STRTAB_BASE: /* 64b */ + val =3D smmu_read64(s->strtab_base, 0, size); + break; + case A_STRTAB_BASE + 4: /* 64b */ + val =3D smmu_read64(s->strtab_base, 4, size); + break; + case A_STRTAB_BASE_CFG: + val =3D s->strtab_base_cfg; + break; + case A_CMDQ_BASE: /* 64b */ + val =3D smmu_read64(s->cmdq.base, 0, size); + break; + case A_CMDQ_BASE + 4: + val =3D smmu_read64(s->cmdq.base, 4, size); + break; + case A_CMDQ_PROD: + val =3D s->cmdq.prod; + break; + case A_CMDQ_CONS: + val =3D s->cmdq.cons; + break; + case A_EVENTQ_BASE: /* 64b */ + val =3D smmu_read64(s->eventq.base, 0, size); + break; + case A_EVENTQ_BASE + 4: /* 64b */ + val =3D smmu_read64(s->eventq.base, 4, size); + break; + case A_EVENTQ_PROD: + val =3D s->eventq.prod; + break; + case A_EVENTQ_CONS: + val =3D s->eventq.cons; + break; + default: + error_report("%s unhandled access at 0x%"PRIx64, __func__, 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 ARM_SMMUV3(dev); + SMMUv3Class *c =3D ARM_SMMUV3_GET_CLASS(s); + + c->parent_reset(dev); + + smmuv3_init_regs(s); +} + +static void smmu_realize(DeviceState *d, Error **errp) +{ + SMMUState *sys =3D ARM_SMMU(d); + SMMUv3State *s =3D ARM_SMMUV3(sys); + SMMUv3Class *c =3D ARM_SMMUV3_GET_CLASS(s); + SysBusDevice *dev =3D SYS_BUS_DEVICE(d); + Error *local_err =3D NULL; + + c->parent_realize(d, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + memory_region_init_io(&sys->iomem, OBJECT(s), + &smmu_mem_ops, sys, TYPE_ARM_SMMUV3, 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(features, SMMUv3State), + VMSTATE_UINT8(sid_size, SMMUv3State), + VMSTATE_UINT8(sid_split, SMMUv3State), + + VMSTATE_UINT32_ARRAY(idr, SMMUv3State, 6), + VMSTATE_UINT32(iidr, SMMUv3State), + VMSTATE_UINT32_ARRAY(cr, SMMUv3State, 3), + VMSTATE_UINT32(cr0ack, SMMUv3State), + VMSTATE_UINT32(statusr, SMMUv3State), + VMSTATE_UINT32(irq_ctrl, SMMUv3State), + VMSTATE_UINT32(irq_ctrl_ack, SMMUv3State), + VMSTATE_UINT32(gerror, SMMUv3State), + VMSTATE_UINT32(gerrorn, SMMUv3State), + VMSTATE_UINT64(gerror_irq_cfg0, SMMUv3State), + VMSTATE_UINT32(gerror_irq_cfg1, SMMUv3State), + VMSTATE_UINT32(gerror_irq_cfg2, SMMUv3State), + VMSTATE_UINT64(strtab_base, SMMUv3State), + VMSTATE_UINT32(strtab_base_cfg, SMMUv3State), + VMSTATE_UINT64(eventq_irq_cfg0, SMMUv3State), + VMSTATE_UINT32(eventq_irq_cfg1, SMMUv3State), + VMSTATE_UINT32(eventq_irq_cfg2, SMMUv3State), + + VMSTATE_UINT64(cmdq.base, SMMUv3State), + VMSTATE_UINT32(cmdq.prod, SMMUv3State), + VMSTATE_UINT32(cmdq.cons, SMMUv3State), + VMSTATE_UINT8(cmdq.entry_size, SMMUv3State), + VMSTATE_UINT64(eventq.base, SMMUv3State), + VMSTATE_UINT32(eventq.prod, SMMUv3State), + VMSTATE_UINT32(eventq.cons, SMMUv3State), + VMSTATE_UINT8(eventq.entry_size, SMMUv3State), + + 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); + SMMUv3Class *c =3D ARM_SMMUV3_CLASS(klass); + + dc->vmsd =3D &vmstate_smmuv3; + device_class_set_parent_reset(dc, smmu_reset, &c->parent_reset); + c->parent_realize =3D dc->realize; + 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_ARM_SMMUV3, + .parent =3D TYPE_ARM_SMMU, + .instance_size =3D sizeof(SMMUv3State), + .instance_init =3D smmuv3_instance_init, + .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 3584974..64d2b9b 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -12,3 +12,6 @@ smmu_ptw_invalid_pte(int stage, int level, uint64_t basea= ddr, uint64_t pteaddr, smmu_ptw_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 i= ova=3D0x%"PRIx64" base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" = page address =3D 0x%"PRIx64 smmu_ptw_block_pte(int stage, int level, uint64_t baseaddr, uint64_t ptead= dr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "stage=3D%d le= vel=3D%d base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" iova=3D0x= %"PRIx64" block address =3D 0x%"PRIx64" block size =3D %d MiB" 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 + +#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..37a5723 --- /dev/null +++ b/include/hw/arm/smmuv3.h @@ -0,0 +1,91 @@ +/* + * 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, see . + */ + +#ifndef HW_ARM_SMMUV3_H +#define HW_ARM_SMMUV3_H + +#include "hw/arm/smmu-common.h" +#include "hw/registerfields.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; + uint8_t entry_size; +} SMMUQueue; + +typedef struct SMMUv3State { + SMMUState smmu_state; + + /* Local cache of most-frequently used registers */ +#define SMMU_FEATURE_2LVL_STE (1 << 0) + uint32_t features; + uint8_t sid_size; + uint8_t sid_split; + + uint32_t idr[6]; + uint32_t iidr; + uint32_t cr[3]; + uint32_t cr0ack; + uint32_t statusr; + uint32_t irq_ctrl; + uint32_t irq_ctrl_ack; + uint32_t gerror; + uint32_t gerrorn; + uint64_t gerror_irq_cfg0; + uint32_t gerror_irq_cfg1; + uint32_t gerror_irq_cfg2; + uint64_t strtab_base; + uint32_t strtab_base_cfg; + uint64_t eventq_irq_cfg0; + uint32_t eventq_irq_cfg1; + uint32_t eventq_irq_cfg2; + + SMMUQueue eventq, cmdq; + + qemu_irq irq[4]; +} SMMUv3State; + +typedef enum { + SMMU_IRQ_EVTQ, + SMMU_IRQ_PRIQ, + SMMU_IRQ_CMD_SYNC, + SMMU_IRQ_GERROR, +} SMMUIrq; + +typedef struct { + /*< private >*/ + SMMUBaseClass smmu_base_class; + /*< public >*/ + + DeviceRealize parent_realize; + DeviceReset parent_reset; +} SMMUv3Class; + +#define TYPE_ARM_SMMUV3 "arm-smmuv3" +#define ARM_SMMUV3(obj) OBJECT_CHECK(SMMUv3State, (obj), TYPE_ARM_SMMUV3) +#define ARM_SMMUV3_CLASS(klass) \ + OBJECT_CLASS_CHECK(SMMUv3Class, (klass), TYPE_ARM_SMMUV3) +#define ARM_SMMUV3_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SMMUv3Class, (obj), TYPE_ARM_SMMUV3) + +#endif --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518896185102613.5792055580315; Sat, 17 Feb 2018 11:36:25 -0800 (PST) Received: from localhost ([::1]:51954 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8HY-0006MT-3W for importer@patchew.org; Sat, 17 Feb 2018 14:36:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44959) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WE-0003Rw-3g for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:31 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WC-0001dj-5n for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:30 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:43728 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7W5-00016Z-6H; Sat, 17 Feb 2018 13:47:21 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9A4168424C; Sat, 17 Feb 2018 18:47:20 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 095322024CA2; Sat, 17 Feb 2018 18:47:17 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:47 +0100 Message-Id: <1518893216-9983-6-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 17 Feb 2018 18:47:20 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 17 Feb 2018 18:47:20 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 05/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 hence the pulse usage. Signed-off-by: Eric Auger --- v7 -> v8: - remove SMMU_PENDING_GERRORS macro - properly toggle gerror - properly sanitize gerrorn write --- hw/arm/smmuv3-internal.h | 10 ++++++++ hw/arm/smmuv3.c | 64 ++++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 3 +++ 3 files changed, 77 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 5be8303..40b39a1 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -152,4 +152,14 @@ static inline uint64_t smmu_read64(uint64_t r, unsigne= d offset, return extract64(r, offset << 3, 32); } =20 +/* Interrupts */ + +#define smmuv3_eventq_irq_enabled(s) \ + (FIELD_EX32(s->irq_ctrl, IRQ_CTRL, EVENTQ_IRQEN)) +#define smmuv3_gerror_irq_enabled(s) \ + (FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN)) + +void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask); +void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index dc03c9e..8779d3f 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -30,6 +30,70 @@ #include "hw/arm/smmuv3.h" #include "smmuv3-internal.h" =20 +/** + * smmuv3_trigger_irq - pulse @irq if enabled and update + * GERROR register in case of GERROR interrupt + * + * @irq: irq type + * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR) + */ +void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask) +{ + + bool pulse =3D false; + + switch (irq) { + case SMMU_IRQ_EVTQ: + pulse =3D smmuv3_eventq_irq_enabled(s); + break; + case SMMU_IRQ_PRIQ: + error_setg(&error_fatal, "PRI not supported"); + break; + case SMMU_IRQ_CMD_SYNC: + pulse =3D true; + break; + case SMMU_IRQ_GERROR: + { + uint32_t pending =3D s->gerror ^ s->gerrorn; + uint32_t new_gerrors =3D ~pending & gerror_mask; + + if (!new_gerrors) { + /* only toggle non pending errors */ + return; + } + s->gerror ^=3D new_gerrors; + trace_smmuv3_write_gerror(new_gerrors, s->gerror); + + /* pulse the GERROR irq only if all previous gerrors were acked */ + pulse =3D smmuv3_gerror_irq_enabled(s) && !pending; + break; + } + } + if (pulse) { + trace_smmuv3_trigger_irq(irq); + qemu_irq_pulse(s->irq[irq]); + } +} + +void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn) +{ + uint32_t pending =3D s->gerror ^ s->gerrorn; + uint32_t toggled =3D s->gerrorn ^ new_gerrorn; + uint32_t acked; + + if (toggled & ~pending) { + qemu_log_mask(LOG_GUEST_ERROR, + "guest toggles non pending errors =3D 0x%x\n", + toggled & ~pending); + } + + /* Make sure SW does not toggle irqs that are not active */ + acked =3D toggled & pending; + s->gerrorn ^=3D acked; + + trace_smmuv3_write_gerrorn(acked, s->gerrorn); +} + static void smmuv3_init_regs(SMMUv3State *s) { /** diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 64d2b9b..2ddae40 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -15,3 +15,6 @@ smmu_get_pte(uint64_t baseaddr, int index, uint64_t ptead= dr, uint64_t pte) "base =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_trigger_irq(int irq) "irq=3D%d" +smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=3D0x%x, ne= w gerror=3D0x%x" +smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=3D0x%x, new = gerrorn=3D0x%x" --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518897013633152.3630124471083; Sat, 17 Feb 2018 11:50:13 -0800 (PST) Received: from localhost ([::1]:54774 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8Un-0002KM-PM for importer@patchew.org; Sat, 17 Feb 2018 14:50:05 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45037) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WI-0003Wa-CR for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WF-0001rk-GI for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:34 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:41980 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7W8-0001JR-3z; Sat, 17 Feb 2018 13:47:24 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8069C40FB633; Sat, 17 Feb 2018 18:47:23 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id DE8942024CA2; Sat, 17 Feb 2018 18:47:20 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:48 +0100 Message-Id: <1518893216-9983-7-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Sat, 17 Feb 2018 18:47:23 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Sat, 17 Feb 2018 18:47:23 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 06/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" We introduce helpers to read/write into the command and event circular queues. smmuv3_write_eventq and smmuv3_cmq_consume will become static in subsequent patches. Invalidation commands are not yet dealt with. We do not cache data that need to be invalidated. This will change with vhost integration. Signed-off-by: Eric Auger --- v8 -> v9: - fix CMD_SSID & CMD_ADDR + some renamings - do cons increment after the execution of the command - add Q_INCONSISTENT() v7 -> v8 - use address_space_rw - helpers inspired from spec --- hw/arm/smmuv3-internal.h | 150 +++++++++++++++++++++++++++++++++++++++++++ hw/arm/smmuv3.c | 162 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 4 ++ 3 files changed, 316 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 40b39a1..c0771ce 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -162,4 +162,154 @@ static inline uint64_t smmu_read64(uint64_t r, unsign= ed offset, void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask); void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn); =20 +/* Queue Handling */ + +#define LOG2SIZE(q) extract64((q)->base, 0, 5) +#define BASE(q) ((q)->base & SMMU_BASE_ADDR_MASK) +#define WRAP_MASK(q) (1 << LOG2SIZE(q)) +#define INDEX_MASK(q) ((1 << LOG2SIZE(q)) - 1) +#define WRAP_INDEX_MASK(q) ((1 << (LOG2SIZE(q) + 1)) - 1) + +#define Q_CONS_ENTRY(q) (BASE(q) + \ + (q)->entry_size * ((q)->cons & INDEX_MASK(q))) +#define Q_PROD_ENTRY(q) (BASE(q) + \ + (q)->entry_size * ((q)->prod & INDEX_MASK(q))) + +#define Q_CONS(q) ((q)->cons & INDEX_MASK(q)) +#define Q_PROD(q) ((q)->prod & INDEX_MASK(q)) + +#define Q_CONS_WRAP(q) (((q)->cons & WRAP_MASK(q)) >> LOG2SIZE(q)) +#define Q_PROD_WRAP(q) (((q)->prod & WRAP_MASK(q)) >> LOG2SIZE(q)) + +#define Q_FULL(q) \ + (((((q)->cons) & INDEX_MASK(q)) =3D=3D \ + (((q)->prod) & INDEX_MASK(q))) && \ + ((((q)->cons) & WRAP_MASK(q)) !=3D \ + (((q)->prod) & WRAP_MASK(q)))) + +#define Q_EMPTY(q) \ + (((((q)->cons) & INDEX_MASK(q)) =3D=3D \ + (((q)->prod) & INDEX_MASK(q))) && \ + ((((q)->cons) & WRAP_MASK(q)) =3D=3D \ + (((q)->prod) & WRAP_MASK(q)))) + +#define Q_INCONSISTENT(q) \ +((((((q)->prod) & INDEX_MASK(q)) > (((q)->cons) & INDEX_MASK(q))) && \ +((((q)->prod) & WRAP_MASK(q)) !=3D (((q)->cons) & WRAP_MASK(q)))) || \ +(((((q)->prod) & INDEX_MASK(q)) < (((q)->cons) & INDEX_MASK(q))) && \ +((((q)->prod) & WRAP_MASK(q)) =3D=3D (((q)->cons) & WRAP_MASK(q))))) \ + +#define SMMUV3_CMDQ_ENABLED(s) \ + (FIELD_EX32(s->cr[0], CR0, CMDQEN)) + +#define SMMUV3_EVENTQ_ENABLED(s) \ + (FIELD_EX32(s->cr[0], CR0, EVENTQEN)) + +static inline void smmu_write_cmdq_err(SMMUv3State *s, uint32_t err_type) +{ + s->cmdq.cons =3D FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type); +} + +void smmuv3_write_eventq(SMMUv3State *s, Evt *evt); + +/* 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", +}; + +#define SMMU_CMD_STRING(type) ( \ +(type < ARRAY_SIZE(cmd_stringify)) ? cmd_stringify[type] : "UNKNOWN" \ +) + +/* 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_SSEC(x) extract32((x)->word[0], 10, 1) +#define CMD_SSV(x) extract32((x)->word[0], 11, 1) +#define CMD_RESUME_AC(x) extract32((x)->word[0], 12, 1) +#define CMD_RESUME_AB(x) extract32((x)->word[0], 13, 1) +#define CMD_SYNC_CS(x) extract32((x)->word[0], 12, 2) +#define CMD_SSID(x) extract32((x)->word[0], 12, 20) +#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_RESUME_STAG(x) extract32((x)->word[2], 0 , 16) +#define CMD_RESP(x) extract32((x)->word[2], 11, 2) +#define CMD_LEAF(x) extract32((x)->word[2], 0 , 1) +#define CMD_STE_RANGE(x) extract32((x)->word[2], 0 , 5) +#define CMD_ADDR(x) ({ \ + uint64_t high =3D (uint64_t)(x)->word[3]; \ + uint64_t low =3D extract32((x)->word[2], 12, 20); \ + uint64_t addr =3D high << 32 | (low << 12); \ + addr; \ + }) + +int smmuv3_cmdq_consume(SMMUv3State *s); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 8779d3f..0b57215 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -94,6 +94,72 @@ void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_g= errorn) trace_smmuv3_write_gerrorn(acked, s->gerrorn); } =20 +static uint32_t queue_index_inc(uint32_t val, + uint32_t qidx_mask, uint32_t qwrap_mask) +{ + uint32_t i =3D (val + 1) & qidx_mask; + + if (i <=3D (val & qidx_mask)) { + i =3D ((val & qwrap_mask) ^ qwrap_mask) | i; + } else { + i =3D (val & qwrap_mask) | i; + } + return i; +} + +static inline void queue_prod_incr(SMMUQueue *q) +{ + q->prod =3D queue_index_inc(q->prod, INDEX_MASK(q), WRAP_MASK(q)); +} + +static inline void queue_cons_incr(SMMUQueue *q) +{ + q->cons =3D queue_index_inc(q->cons, INDEX_MASK(q), WRAP_MASK(q)); +} + +static inline MemTxResult queue_read(SMMUQueue *q, void *data) +{ + dma_addr_t addr =3D Q_CONS_ENTRY(q); + + return dma_memory_read(&address_space_memory, addr, + (uint8_t *)data, q->entry_size); +} + +static void queue_write(SMMUQueue *q, void *data) +{ + dma_addr_t addr =3D Q_PROD_ENTRY(q); + MemTxResult ret; + + ret =3D dma_memory_write(&address_space_memory, addr, + (uint8_t *)data, q->entry_size); + if (ret !=3D MEMTX_OK) { + return; + } + + queue_prod_incr(q); +} + +void smmuv3_write_eventq(SMMUv3State *s, Evt *evt) +{ + SMMUQueue *q =3D &s->eventq; + bool q_empty =3D Q_EMPTY(q); + bool q_full =3D Q_FULL(q); + + if (!SMMUV3_EVENTQ_ENABLED(s)) { + return; + } + + if (q_full) { + return; + } + + queue_write(q, evt); + + if (q_empty) { + smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0); + } +} + static void smmuv3_init_regs(SMMUv3State *s) { /** @@ -133,6 +199,102 @@ static void smmuv3_init_regs(SMMUv3State *s) s->sid_split =3D 0; } =20 +int smmuv3_cmdq_consume(SMMUv3State *s) +{ + SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; + SMMUQueue *q =3D &s->cmdq; + uint32_t type =3D 0; + + if (!SMMUV3_CMDQ_ENABLED(s)) { + return 0; + } + /* + * some commands depend on register values, as above. In case those + * register values change while handling the command, spec says it + * is UNPREDICTABLE whether the command is interpreted under the new + * or old value. + */ + + while (!Q_EMPTY(q)) { + uint32_t pending =3D s->gerror ^ s->gerrorn; + Cmd cmd; + + trace_smmuv3_cmdq_consume(Q_PROD(q), Q_CONS(q), + Q_PROD_WRAP(q), Q_CONS_WRAP(q)); + + if (FIELD_EX32(pending, GERROR, CMDQ_ERR)) { + break; + } + + if (queue_read(q, &cmd) !=3D MEMTX_OK) { + cmd_error =3D SMMU_CERROR_ABT; + break; + } + + type =3D CMD_TYPE(&cmd); + + trace_smmuv3_cmdq_opcode(SMMU_CMD_STRING(type)); + + switch (type) { + case SMMU_CMD_SYNC: + if (CMD_SYNC_CS(&cmd) & CMD_SYNC_SIG_IRQ) { + smmuv3_trigger_irq(s, SMMU_IRQ_CMD_SYNC, 0); + } + break; + case SMMU_CMD_PREFETCH_CONFIG: + case SMMU_CMD_PREFETCH_ADDR: + case SMMU_CMD_CFGI_STE: + case SMMU_CMD_CFGI_STE_RANGE: /* same as SMMU_CMD_CFGI_ALL */ + case SMMU_CMD_CFGI_CD: + case SMMU_CMD_CFGI_CD_ALL: + case SMMU_CMD_TLBI_NH_ALL: + case SMMU_CMD_TLBI_NH_ASID: + case SMMU_CMD_TLBI_NH_VA: + 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: + 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) { + break; + } + /* + * We only increment the cons index after the completion of + * the command. We do that because the SYNC returns immediatly + * and do not check the completion of previous commands + */ + queue_cons_incr(q); + } + + if (cmd_error) { + error_report("Error on %s command execution: %d", + SMMU_CMD_STRING(type), cmd_error); + smmu_write_cmdq_err(s, cmd_error); + smmuv3_trigger_irq(s, SMMU_IRQ_GERROR, R_GERROR_CMDQ_ERR_MASK); + } + + trace_smmuv3_cmdq_consume_out(Q_PROD(q), Q_CONS(q), + Q_PROD_WRAP(q), Q_CONS_WRAP(q)); + + return 0; +} + static void smmu_write_mmio(void *opaque, hwaddr addr, uint64_t val, unsigned size) { diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 2ddae40..1c5105d 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -18,3 +18,7 @@ smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size= ) "addr: 0x%"PRIx64" va smmuv3_trigger_irq(int irq) "irq=3D%d" smmuv3_write_gerror(uint32_t toggled, uint32_t gerror) "toggled=3D0x%x, ne= w gerror=3D0x%x" smmuv3_write_gerrorn(uint32_t acked, uint32_t gerrorn) "acked=3D0x%x, new = gerrorn=3D0x%x" +smmuv3_unhandled_cmd(uint32_t type) "Unhandled command type=3D%d" +smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8= _t cons_wrap) "prod=3D%d cons=3D%d prod.wrap=3D%d cons.wrap=3D%d" +smmuv3_cmdq_opcode(const char *opcode) "<--- %s" +smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, u= int8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d " --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518896909076377.5709938034739; Sat, 17 Feb 2018 11:48:29 -0800 (PST) Received: from localhost ([::1]:54636 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8TE-0000zK-Bz for importer@patchew.org; Sat, 17 Feb 2018 14:48:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45078) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WM-0003a8-0N for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WG-0001zE-VG for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:38 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36094 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WA-0001WJ-UP; Sat, 17 Feb 2018 13:47:27 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 617DCEAE83; Sat, 17 Feb 2018 18:47:26 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id C49152024CA2; Sat, 17 Feb 2018 18:47:23 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:49 +0100 Message-Id: <1518893216-9983-8-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 17 Feb 2018 18:47:26 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 17 Feb 2018 18:47:26 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 07/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Now we have relevant helpers for queue and irq management, let's implement MMIO write operations. Signed-off-by: Eric Auger --- v7 -> v8: - precise in the commit message invalidation commands are not yet treated. - use new queue helpers - do not decode unhandled commands at this stage --- hw/arm/smmuv3-internal.h | 24 +++++++--- hw/arm/smmuv3.c | 111 +++++++++++++++++++++++++++++++++++++++++++= ++-- hw/arm/trace-events | 6 +++ 3 files changed, 132 insertions(+), 9 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index c0771ce..5af97ae 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -152,6 +152,25 @@ static inline uint64_t smmu_read64(uint64_t r, unsigne= d offset, return extract64(r, offset << 3, 32); } =20 +static inline void smmu_write64(uint64_t *r, unsigned offset, + unsigned size, uint64_t value) +{ + if (size =3D=3D 8 && !offset) { + *r =3D value; + } + + /* 32 bit access */ + + if (offset && offset !=3D 4) { + qemu_log_mask(LOG_GUEST_ERROR, + "SMMUv3 MMIO write: bad offset/size %u/%u\n", + offset, size); + return ; + } + + *r =3D deposit64(*r, offset << 3, 32, value); +} + /* Interrupts */ =20 #define smmuv3_eventq_irq_enabled(s) \ @@ -159,9 +178,6 @@ static inline uint64_t smmu_read64(uint64_t r, unsigned= offset, #define smmuv3_gerror_irq_enabled(s) \ (FIELD_EX32(s->irq_ctrl, IRQ_CTRL, GERROR_IRQEN)) =20 -void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask); -void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t gerrorn); - /* Queue Handling */ =20 #define LOG2SIZE(q) extract64((q)->base, 0, 5) @@ -310,6 +326,4 @@ enum { /* Command completion notification */ addr; \ }) =20 -int smmuv3_cmdq_consume(SMMUv3State *s); - #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 0b57215..fcfdbb0 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -37,7 +37,8 @@ * @irq: irq type * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR) */ -void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask) +static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, + uint32_t gerror_mask) { =20 bool pulse =3D false; @@ -75,7 +76,7 @@ void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint= 32_t gerror_mask) } } =20 -void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn) +static void smmuv3_write_gerrorn(SMMUv3State *s, uint32_t new_gerrorn) { uint32_t pending =3D s->gerror ^ s->gerrorn; uint32_t toggled =3D s->gerrorn ^ new_gerrorn; @@ -199,7 +200,7 @@ static void smmuv3_init_regs(SMMUv3State *s) s->sid_split =3D 0; } =20 -int smmuv3_cmdq_consume(SMMUv3State *s) +static int smmuv3_cmdq_consume(SMMUv3State *s) { SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; SMMUQueue *q =3D &s->cmdq; @@ -298,7 +299,109 @@ int smmuv3_cmdq_consume(SMMUv3State *s) static void smmu_write_mmio(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - /* not yet implemented */ + SMMUState *sys =3D opaque; + SMMUv3State *s =3D ARM_SMMUV3(sys); + + /* CONSTRAINED UNPREDICTABLE choice to have page0/1 be exact aliases */ + addr &=3D ~0x10000; + + if (size !=3D 4 && size !=3D 8) { + qemu_log_mask(LOG_GUEST_ERROR, + "SMMUv3 MMIO write: bad size %u\n", size); + } + + trace_smmuv3_write_mmio(addr, val, size); + + switch (addr) { + case A_CR0: + s->cr[0] =3D val; + s->cr0ack =3D val; + /* in case the command queue has been enabled */ + smmuv3_cmdq_consume(s); + return; + case A_CR1: + s->cr[1] =3D val; + return; + case A_CR2: + s->cr[2] =3D val; + return; + case A_IRQ_CTRL: + s->irq_ctrl =3D val; + return; + case A_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 A_GERROR_IRQ_CFG0: /* 64b */ + smmu_write64(&s->gerror_irq_cfg0, 0, size, val); + return; + case A_GERROR_IRQ_CFG0 + 4: + smmu_write64(&s->gerror_irq_cfg0, 4, size, val); + return; + case A_GERROR_IRQ_CFG1: + s->gerror_irq_cfg1 =3D val; + return; + case A_GERROR_IRQ_CFG2: + s->gerror_irq_cfg2 =3D val; + return; + case A_STRTAB_BASE: /* 64b */ + smmu_write64(&s->strtab_base, 0, size, val); + return; + case A_STRTAB_BASE + 4: + smmu_write64(&s->strtab_base, 4, size, val); + return; + case A_STRTAB_BASE_CFG: + s->strtab_base_cfg =3D val; + if (FIELD_EX32(val, STRTAB_BASE_CFG, FMT) =3D=3D 1) { + s->sid_split =3D FIELD_EX32(val, STRTAB_BASE_CFG, SPLIT); + s->features |=3D SMMU_FEATURE_2LVL_STE; + } + return; + case A_CMDQ_BASE: /* 64b */ + smmu_write64(&s->cmdq.base, 0, size, val); + return; + case A_CMDQ_BASE + 4: /* 64b */ + smmu_write64(&s->cmdq.base, 4, size, val); + return; + case A_CMDQ_PROD: + s->cmdq.prod =3D val; + smmuv3_cmdq_consume(s); + return; + case A_CMDQ_CONS: + s->cmdq.cons =3D val; + return; + case A_EVENTQ_BASE: /* 64b */ + smmu_write64(&s->eventq.base, 0, size, val); + return; + case A_EVENTQ_BASE + 4: + smmu_write64(&s->eventq.base, 4, size, val); + return; + case A_EVENTQ_PROD: + s->eventq.prod =3D val; + return; + case A_EVENTQ_CONS: + s->eventq.cons =3D val; + return; + case A_EVENTQ_IRQ_CFG0: /* 64b */ + s->eventq.prod =3D val; + smmu_write64(&s->eventq_irq_cfg0, 0, size, val); + return; + case A_EVENTQ_IRQ_CFG0 + 4: + smmu_write64(&s->eventq_irq_cfg0, 4, size, val); + return; + case A_EVENTQ_IRQ_CFG1: + s->eventq_irq_cfg1 =3D val; + return; + case A_EVENTQ_IRQ_CFG2: + s->eventq_irq_cfg2 =3D val; + return; + default: + error_report("%s unhandled access at 0x%"PRIx64, __func__, addr); + } } =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 1c5105d..ed5dce0 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -22,3 +22,9 @@ smmuv3_unhandled_cmd(uint32_t type) "Unhandled command ty= pe=3D%d" smmuv3_cmdq_consume(uint32_t prod, uint32_t cons, uint8_t prod_wrap, uint8= _t cons_wrap) "prod=3D%d cons=3D%d prod.wrap=3D%d cons.wrap=3D%d" smmuv3_cmdq_opcode(const char *opcode) "<--- %s" smmuv3_cmdq_consume_out(uint32_t prod, uint32_t cons, uint8_t prod_wrap, u= int8_t cons_wrap) "prod:%d, cons:%d, prod_wrap:%d, cons_wrap:%d " +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_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 Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518895716989108.78698284352868; Sat, 17 Feb 2018 11:28:36 -0800 (PST) Received: from localhost ([::1]:50398 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en89v-0006r4-9Q for importer@patchew.org; Sat, 17 Feb 2018 14:28:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45126) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WO-0003cU-2c for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WM-0002QD-46 for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:40 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:56734 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WD-0001jB-SP; Sat, 17 Feb 2018 13:47:30 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 423998182D06; Sat, 17 Feb 2018 18:47:29 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id A55B12024CA2; Sat, 17 Feb 2018 18:47:26 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:50 +0100 Message-Id: <1518893216-9983-9-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 17 Feb 2018 18:47:29 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 17 Feb 2018 18:47:29 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 08/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Let's introduce a helper function aiming at recording an event in the event queue. Signed-off-by: Eric Auger --- v8 -> v9: - add SMMU_EVENT_STRING v7 -> v8: - use dma_addr_t instead of hwaddr in smmuv3_record_event() - introduce struct SMMUEventInfo - add event_stringify + helpers for all fields --- hw/arm/smmuv3-internal.h | 140 +++++++++++++++++++++++++++++++++++++++++++= +++- hw/arm/smmuv3.c | 91 +++++++++++++++++++++++++++++- hw/arm/trace-events | 1 + 3 files changed, 229 insertions(+), 3 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 5af97ae..3929f69 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -226,8 +226,6 @@ static inline void smmu_write_cmdq_err(SMMUv3State *s, = uint32_t err_type) s->cmdq.cons =3D FIELD_DP32(s->cmdq.cons, CMDQ_CONS, ERR, err_type); } =20 -void smmuv3_write_eventq(SMMUv3State *s, Evt *evt); - /* Commands */ =20 enum { @@ -326,4 +324,142 @@ enum { /* Command completion notification */ addr; \ }) =20 +/* Events */ + +typedef enum SMMUEventType { + SMMU_EVT_OK =3D 0x00, + SMMU_EVT_F_UUT =3D 0x01, + SMMU_EVT_C_BAD_STREAMID =3D 0x02, + SMMU_EVT_F_STE_FETCH =3D 0x03, + SMMU_EVT_C_BAD_STE =3D 0x04, + SMMU_EVT_F_BAD_ATS_TREQ =3D 0x05, + SMMU_EVT_F_STREAM_DISABLED =3D 0x06, + SMMU_EVT_F_TRANS_FORBIDDEN =3D 0x07, + SMMU_EVT_C_BAD_SUBSTREAMID =3D 0x08, + SMMU_EVT_F_CD_FETCH =3D 0x09, + SMMU_EVT_C_BAD_CD =3D 0x0a, + SMMU_EVT_F_WALK_EABT =3D 0x0b, + SMMU_EVT_F_TRANSLATION =3D 0x10, + SMMU_EVT_F_ADDR_SIZE =3D 0x11, + SMMU_EVT_F_ACCESS =3D 0x12, + SMMU_EVT_F_PERMISSION =3D 0x13, + SMMU_EVT_F_TLB_CONFLICT =3D 0x20, + SMMU_EVT_F_CFG_CONFLICT =3D 0x21, + SMMU_EVT_E_PAGE_REQ =3D 0x24, +} SMMUEventType; + +static const char *event_stringify[] =3D { + [SMMU_EVT_OK] =3D "SMMU_EVT_OK", + [SMMU_EVT_F_UUT] =3D "SMMU_EVT_F_UUT", + [SMMU_EVT_C_BAD_STREAMID] =3D "SMMU_EVT_C_BAD_STREAMID", + [SMMU_EVT_F_STE_FETCH] =3D "SMMU_EVT_F_STE_FETCH", + [SMMU_EVT_C_BAD_STE] =3D "SMMU_EVT_C_BAD_STE", + [SMMU_EVT_F_BAD_ATS_TREQ] =3D "SMMU_EVT_F_BAD_ATS_TREQ", + [SMMU_EVT_F_STREAM_DISABLED] =3D "SMMU_EVT_F_STREAM_DISABLED", + [SMMU_EVT_F_TRANS_FORBIDDEN] =3D "SMMU_EVT_F_TRANS_FORBIDDEN", + [SMMU_EVT_C_BAD_SUBSTREAMID] =3D "SMMU_EVT_C_BAD_SUBSTREAMID", + [SMMU_EVT_F_CD_FETCH] =3D "SMMU_EVT_F_CD_FETCH", + [SMMU_EVT_C_BAD_CD] =3D "SMMU_EVT_C_BAD_CD", + [SMMU_EVT_F_WALK_EABT] =3D "SMMU_EVT_F_WALK_EABT", + [SMMU_EVT_F_TRANSLATION] =3D "SMMU_EVT_F_TRANSLATION", + [SMMU_EVT_F_ADDR_SIZE] =3D "SMMU_EVT_F_ADDR_SIZE", + [SMMU_EVT_F_ACCESS] =3D "SMMU_EVT_F_ACCESS", + [SMMU_EVT_F_PERMISSION] =3D "SMMU_EVT_F_PERMISSION", + [SMMU_EVT_F_TLB_CONFLICT] =3D "SMMU_EVT_F_TLB_CONFLICT", + [SMMU_EVT_F_CFG_CONFLICT] =3D "SMMU_EVT_F_CFG_CONFLICT", + [SMMU_EVT_E_PAGE_REQ] =3D "SMMU_EVT_E_PAGE_REQ", +}; + +#define SMMU_EVENT_STRING(event) ( = \ +(event < ARRAY_SIZE(event_stringify)) ? event_stringify[event] : "UNKNOWN"= \ +) + +typedef struct SMMUEventInfo { + SMMUEventType type; + uint32_t sid; + bool recorded; + bool record_trans_faults; + union { + struct { + uint32_t ssid; + bool ssv; + dma_addr_t addr; + bool rnw; + bool pnu; + bool ind; + } f_uut; + struct ssid_info { + uint32_t ssid; + bool ssv; + } c_bad_streamid; + struct ssid_addr_info { + uint32_t ssid; + bool ssv; + dma_addr_t addr; + } f_ste_fetch; + struct ssid_info c_bad_ste; + struct { + dma_addr_t addr; + bool rnw; + } f_transl_forbidden; + struct { + uint32_t ssid; + } c_bad_substream; + struct ssid_addr_info f_cd_fetch; + struct ssid_info c_bad_cd; + struct full_info { + bool stall; + uint16_t stag; + uint32_t ssid; + bool ssv; + bool s2; + dma_addr_t addr; + bool rnw; + bool pnu; + bool ind; + uint8_t class; + dma_addr_t addr2; + } f_walk_eabt; + struct full_info f_translation; + struct full_info f_addr_size; + struct full_info f_access; + struct full_info f_permission; + struct ssid_info f_cfg_conflict; + /** + * not supported yet: + * F_BAD_ATS_TREQ + * F_BAD_ATS_TREQ + * F_TLB_CONFLICT + * E_PAGE_REQUEST + * IMPDEF_EVENTn + */ + } u; +} SMMUEventInfo; + +/* EVTQ fields */ + +#define EVT_Q_OVERFLOW (1 << 31) + +#define EVT_SET_TYPE(x, v) deposit32((x)->word[0], 0 , 8 , v) +#define EVT_SET_SSV(x, v) deposit32((x)->word[0], 11, 1 , v) +#define EVT_SET_SSID(x, v) deposit32((x)->word[0], 12, 20, v) +#define EVT_SET_SID(x, v) ((x)->word[1] =3D v) +#define EVT_SET_STAG(x, v) deposit32((x)->word[2], 0 , 16, v) +#define EVT_SET_STALL(x, v) deposit32((x)->word[2], 31, 1 , v) +#define EVT_SET_PNU(x, v) deposit32((x)->word[3], 1 , 1 , v) +#define EVT_SET_IND(x, v) deposit32((x)->word[3], 2 , 1 , v) +#define EVT_SET_RNW(x, v) deposit32((x)->word[3], 3 , 1 , v) +#define EVT_SET_S2(x, v) deposit32((x)->word[3], 7 , 1 , v) +#define EVT_SET_CLASS(x, v) deposit32((x)->word[3], 8 , 2 , v) +#define EVT_SET_ADDR(x, addr) ({ \ + (x)->word[5] =3D (uint32_t)(addr >> 32); \ + (x)->word[4] =3D (uint32_t)(addr & 0xffffffff); \ + }) +#define EVT_SET_ADDR2(x, addr) ({ \ + deposit32((x)->word[7], 3, 29, addr >> 16); \ + deposit32((x)->word[7], 0, 16, addr & 0xffff); \ + }) + +void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index fcfdbb0..0adfe53 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -140,7 +140,7 @@ static void queue_write(SMMUQueue *q, void *data) queue_prod_incr(q); } =20 -void smmuv3_write_eventq(SMMUv3State *s, Evt *evt) +static void smmuv3_write_eventq(SMMUv3State *s, Evt *evt) { SMMUQueue *q =3D &s->eventq; bool q_empty =3D Q_EMPTY(q); @@ -161,6 +161,95 @@ void smmuv3_write_eventq(SMMUv3State *s, Evt *evt) } } =20 +void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *info) +{ + Evt evt; + + if (!SMMUV3_EVENTQ_ENABLED(s)) { + return; + } + + EVT_SET_TYPE(&evt, info->type); + EVT_SET_SID(&evt, info->sid); + + switch (info->type) { + case SMMU_EVT_OK: + return; + case SMMU_EVT_F_UUT: + EVT_SET_SSID(&evt, info->u.f_uut.ssid); + EVT_SET_SSV(&evt, info->u.f_uut.ssv); + EVT_SET_ADDR(&evt, info->u.f_uut.addr); + EVT_SET_RNW(&evt, info->u.f_uut.rnw); + EVT_SET_PNU(&evt, info->u.f_uut.pnu); + EVT_SET_IND(&evt, info->u.f_uut.ind); + break; + case SMMU_EVT_C_BAD_STREAMID: + EVT_SET_SSID(&evt, info->u.c_bad_streamid.ssid); + EVT_SET_SSV(&evt, info->u.c_bad_streamid.ssv); + break; + case SMMU_EVT_F_STE_FETCH: + EVT_SET_SSID(&evt, info->u.f_ste_fetch.ssid); + EVT_SET_SSV(&evt, info->u.f_ste_fetch.ssv); + EVT_SET_ADDR(&evt, info->u.f_ste_fetch.addr); + break; + case SMMU_EVT_C_BAD_STE: + EVT_SET_SSID(&evt, info->u.c_bad_ste.ssid); + EVT_SET_SSV(&evt, info->u.c_bad_ste.ssv); + break; + case SMMU_EVT_F_STREAM_DISABLED: + break; + case SMMU_EVT_F_TRANS_FORBIDDEN: + EVT_SET_ADDR(&evt, info->u.f_transl_forbidden.addr); + EVT_SET_RNW(&evt, info->u.f_transl_forbidden.rnw); + break; + case SMMU_EVT_C_BAD_SUBSTREAMID: + EVT_SET_SSID(&evt, info->u.c_bad_substream.ssid); + break; + case SMMU_EVT_F_CD_FETCH: + EVT_SET_SSID(&evt, info->u.f_cd_fetch.ssid); + EVT_SET_SSV(&evt, info->u.f_cd_fetch.ssv); + EVT_SET_ADDR(&evt, info->u.f_cd_fetch.addr); + break; + case SMMU_EVT_C_BAD_CD: + EVT_SET_SSID(&evt, info->u.c_bad_cd.ssid); + EVT_SET_SSV(&evt, info->u.c_bad_cd.ssv); + break; + case SMMU_EVT_F_WALK_EABT: + case SMMU_EVT_F_TRANSLATION: + case SMMU_EVT_F_ADDR_SIZE: + case SMMU_EVT_F_ACCESS: + case SMMU_EVT_F_PERMISSION: + EVT_SET_STALL(&evt, info->u.f_walk_eabt.stall); + EVT_SET_STAG(&evt, info->u.f_walk_eabt.stag); + EVT_SET_SSID(&evt, info->u.f_walk_eabt.ssid); + EVT_SET_SSV(&evt, info->u.f_walk_eabt.ssv); + EVT_SET_S2(&evt, info->u.f_walk_eabt.s2); + EVT_SET_ADDR(&evt, info->u.f_walk_eabt.addr); + EVT_SET_RNW(&evt, info->u.f_walk_eabt.rnw); + EVT_SET_PNU(&evt, info->u.f_walk_eabt.pnu); + EVT_SET_IND(&evt, info->u.f_walk_eabt.ind); + EVT_SET_CLASS(&evt, info->u.f_walk_eabt.class); + EVT_SET_ADDR2(&evt, info->u.f_walk_eabt.addr2); + break; + case SMMU_EVT_F_CFG_CONFLICT: + EVT_SET_SSID(&evt, info->u.f_cfg_conflict.ssid); + EVT_SET_SSV(&evt, info->u.f_cfg_conflict.ssv); + break; + /* rest is not implemented */ + case SMMU_EVT_F_BAD_ATS_TREQ: + case SMMU_EVT_F_TLB_CONFLICT: + case SMMU_EVT_E_PAGE_REQ: + default: + error_report("%s event %d not supported", __func__, + info->type); + return; + } + + trace_smmuv3_record_event(SMMU_EVENT_STRING(info->type), info->sid); + smmuv3_write_eventq(s, &evt); + info->recorded =3D true; +} + static void smmuv3_init_regs(SMMUv3State *s) { /** diff --git a/hw/arm/trace-events b/hw/arm/trace-events index ed5dce0..c79c15e 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -28,3 +28,4 @@ smmuv3_write_mmio(hwaddr addr, uint64_t val, unsigned siz= e) "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_record_event(const char *type, uint32_t sid) "%s sid=3D%d" --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518897191874191.3866251411124; Sat, 17 Feb 2018 11:53:11 -0800 (PST) Received: from localhost ([::1]:54999 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8Xk-0004eS-2U for importer@patchew.org; Sat, 17 Feb 2018 14:53:08 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45226) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WS-0003iE-QZ for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WP-0002j0-PP for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:44 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:41992 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WG-0001wQ-Pu; Sat, 17 Feb 2018 13:47:32 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2C68040FB639; Sat, 17 Feb 2018 18:47:32 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 861032024CA2; Sat, 17 Feb 2018 18:47:29 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:51 +0100 Message-Id: <1518893216-9983-10-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Sat, 17 Feb 2018 18:47:32 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Sat, 17 Feb 2018 18:47:32 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 09/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This patch 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 --- v8 -> v9: - use SMMU_EVENT_STRING macro - get rid of last erro_report's - decode asid - handle config abort before ptw - add 64-bit single-copy atomic comment v7 -> v8: - use address_space_rw - s/Ste/STE, s/Cd/CD - use dma_memory_read - remove everything related to stage 2 - collect data for both TTx - renamings - pass the event handle all along the config decoding path - decode tbi, ars --- hw/arm/smmuv3-internal.h | 146 ++++++++++++++++++++ hw/arm/smmuv3.c | 341 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 9 ++ 3 files changed, 496 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 3929f69..b203426 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -462,4 +462,150 @@ typedef struct SMMUEventInfo { =20 void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo *event); =20 +/* Configuration Data */ + +/* STE Level 1 Descriptor */ +typedef struct STEDesc { + uint32_t word[2]; +} STEDesc; + +/* CD Level 1 Descriptor */ +typedef struct CDDesc { + uint32_t word[2]; +} CDDesc; + +/* Stream Table Entry(STE) */ +typedef struct STE { + uint32_t word[16]; +} STE; + +/* Context Descriptor(CD) */ +typedef struct CD { + uint32_t word[16]; +} CD; + +/* STE fields */ + +#define STE_VALID(x) extract32((x)->word[0], 0, 1) /* 0 */ + +#define STE_CONFIG(x) extract32((x)->word[0], 1, 3) +#define STE_CFG_S1_ENABLED(config) (config & 0x1) +#define STE_CFG_S2_ENABLED(config) (config & 0x2) +#define STE_CFG_ABORT(config) (!(config & 0x4)) +#define STE_CFG_BYPASS(config) (config =3D=3D 0x4) + +#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 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_ENDI(x) extract32((x)->word[0], 15, 1) +#define CD_IPS(x) extract32((x)->word[1], 0 , 3) +#define CD_TBI(x) extract32((x)->word[1], 6 , 2) +#define CD_S(x) extract32((x)->word[1], 12, 1) +#define CD_R(x) extract32((x)->word[1], 13, 1) +#define CD_A(x) extract32((x)->word[1], 14, 1) +#define CD_AARCH64(x) extract32((x)->word[1], 9 , 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 ttbr in use + * @bits: TG0/1 fields + * @ttbr: ttbr index in use + */ +static inline int tg2granule(int bits, int ttbr) +{ + switch (bits) { + case 1: + return ttbr ? 14 : 16; + case 2: + return ttbr ? 12 : 14; + case 3: + return ttbr ? 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)) + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 0adfe53..384393f 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -289,6 +289,344 @@ static void smmuv3_init_regs(SMMUv3State *s) s->sid_split =3D 0; } =20 +static int smmu_get_ste(SMMUv3State *s, dma_addr_t addr, STE *buf, + SMMUEventInfo *event) +{ + int ret; + + trace_smmuv3_get_ste(addr); + /* TODO: guarantee 64-bit single-copy atomicity */ + ret =3D dma_memory_read(&address_space_memory, addr, + (void *)buf, sizeof(*buf)); + if (ret !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "Cannot fetch pte at address=3D0x%"PRIx64"\n", addr); + event->type =3D SMMU_EVT_F_STE_FETCH; + event->u.f_ste_fetch.addr =3D addr; + return -EINVAL; + } + return 0; + +} + +/* @ssid > 0 not supported yet */ +static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid, + CD *buf, SMMUEventInfo *event) +{ + dma_addr_t addr =3D STE_CTXPTR(ste); + int ret; + + trace_smmuv3_get_cd(addr); + /* TODO: guarantee 64-bit single-copy atomicity */ + ret =3D dma_memory_read(&address_space_memory, addr, + (void *)buf, sizeof(*buf)); + if (ret !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "Cannot fetch pte at address=3D0x%"PRIx64"\n", addr); + event->type =3D SMMU_EVT_F_CD_FETCH; + event->u.f_ste_fetch.addr =3D addr; + return -EINVAL; + } + return 0; +} + +static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg, + STE *ste, SMMUEventInfo *event) +{ + uint32_t config =3D STE_CONFIG(ste); + int ret =3D -EINVAL; + + if (STE_CFG_ABORT(config)) { + /* abort but don't record any event */ + cfg->aborted =3D true; + return ret; + } + + if (STE_CFG_BYPASS(config)) { + cfg->bypassed =3D true; + return ret; + } + + if (!STE_VALID(ste)) { + goto bad_ste; + } + + if (STE_CFG_S2_ENABLED(config)) { + error_setg(&error_fatal, "SMMUv3 does not support stage 2 yet"); + } + + if (STE_S1CDMAX(ste) !=3D 0) { + error_setg(&error_fatal, + "SMMUv3 does not support multiple context descriptors y= et"); + goto bad_ste; + } + return 0; + +bad_ste: + event->type =3D SMMU_EVT_C_BAD_STE; + return -EINVAL; +} + +/** + * smmu_find_ste - Return the stream table entry associated + * to the sid + * + * @s: smmuv3 handle + * @sid: stream ID + * @ste: returned stream table entry + * @event: handle to an event info + * + * Supports linear and 2-level stream table + * Return 0 on success, -EINVAL otherwise + */ +static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, + SMMUEventInfo *event) +{ + dma_addr_t addr; + int ret; + + trace_smmuv3_find_ste(sid, s->features, s->sid_split); + /* Check SID range */ + if (sid > (1 << SMMU_IDR1_SIDSIZE)) { + event->type =3D SMMU_EVT_C_BAD_STREAMID; + return -EINVAL; + } + if (s->features & SMMU_FEATURE_2LVL_STE) { + int l1_ste_offset, l2_ste_offset, max_l2_ste, span; + dma_addr_t strtab_base, l1ptr, l2ptr; + STEDesc l1std; + + strtab_base =3D s->strtab_base & SMMU_BASE_ADDR_MASK; + l1_ste_offset =3D sid >> s->sid_split; + l2_ste_offset =3D sid & ((1 << s->sid_split) - 1); + l1ptr =3D (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)= ); + /* TODO: guarantee 64-bit single-copy atomicity */ + ret =3D dma_memory_read(&address_space_memory, l1ptr, + (uint8_t *)&l1std, sizeof(l1std)); + if (ret !=3D MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, + "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr); + event->type =3D SMMU_EVT_F_STE_FETCH; + event->u.f_ste_fetch.addr =3D l1ptr; + return -EINVAL; + } + + span =3D L1STD_SPAN(&l1std); + + if (!span) { + /* l2ptr is not valid */ + qemu_log_mask(LOG_GUEST_ERROR, + "invalid sid=3D%d (L1STD span=3D0)\n", sid); + event->type =3D SMMU_EVT_C_BAD_STREAMID; + return -EINVAL; + } + 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) { + qemu_log_mask(LOG_GUEST_ERROR, + "l2_ste_offset=3D%d > max_l2_ste=3D%d\n", + l2_ste_offset, max_l2_ste); + event->type =3D SMMU_EVT_C_BAD_STE; + return -EINVAL; + } + 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, event)) { + return -EINVAL; + } + + return 0; +} + +static int decode_cd(SMMUTransCfg *cfg, CD *cd, SMMUEventInfo *event) +{ + int ret =3D -EINVAL; + int i; + + if (!CD_VALID(cd) || !CD_AARCH64(cd)) { + goto error; + } + + /* we support only those at the moment */ + cfg->aa64 =3D true; + cfg->stage =3D 1; + + cfg->oas =3D oas2bits(CD_IPS(cd)); + cfg->oas =3D MIN(oas2bits(SMMU_IDR5_OAS), cfg->oas); + cfg->tbi =3D CD_TBI(cd); + cfg->asid =3D CD_ASID(cd); + + trace_smmuv3_decode_cd(cfg->oas); + + /* decode data dependent on TT */ + for (i =3D 0; i <=3D 1; i++) { + int tg, tsz; + SMMUTransTableInfo *tt =3D &cfg->tt[i]; + + cfg->tt[i].disabled =3D CD_EPD(cd, i); + if (cfg->tt[i].disabled) { + continue; + } + + tsz =3D CD_TSZ(cd, i); + if (tsz < 16 || tsz > 39) { + goto error; + } + + tg =3D CD_TG(cd, i); + tt->granule_sz =3D tg2granule(tg, i); + if ((tt->granule_sz !=3D 12 && tt->granule_sz !=3D 16) || CD_ENDI(= cd)) { + goto error; + } + + tt->tsz =3D tsz; + tt->initial_level =3D 4 - (64 - tsz - 4) / (tt->granule_sz - 3); + tt->ttb =3D CD_TTB(cd, i); + tt->ttb =3D extract64(tt->ttb, 0, cfg->oas); + trace_smmuv3_decode_cd_tt(i, tt->tsz, tt->ttb, + tt->granule_sz, tt->initial_level); + } + + event->record_trans_faults =3D CD_R(cd); + + return 0; + +error: + event->type =3D SMMU_EVT_C_BAD_CD; + return ret; +} + +/** + * 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 which is populated through + * the different configuration decodng steps + * @event: must be zero'ed by the caller + * + * return < 0 if the translation needs to be aborted (@event is filled + * accordingly). Return 0 otherwise. + */ +static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg, + SMMUEventInfo *event) +{ + SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); + uint32_t sid =3D smmu_get_sid(sdev); + SMMUv3State *s =3D sdev->smmu; + int ret =3D -EINVAL; + STE ste; + CD cd; + + if (smmu_find_ste(s, sid, &ste, event)) { + return ret; + } + + if (decode_ste(s, cfg, &ste, event)) { + return ret; + } + + if (smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event)) { + return ret; + } + + return decode_cd(cfg, &cd, event); +} + +static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, + IOMMUAccessFlags flag) +{ + SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); + SMMUv3State *s =3D sdev->smmu; + uint32_t sid =3D smmu_get_sid(sdev); + SMMUEventInfo event =3D {.type =3D SMMU_EVT_OK, .sid =3D sid}; + SMMUPTWEventInfo ptw_info =3D {}; + 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 IOMMU_NONE, + }; + int ret =3D 0; + + if (!smmu_enabled(s)) { + goto out; + } + + ret =3D smmuv3_decode_config(mr, &cfg, &event); + if (ret) { + goto out; + } + + if (cfg.aborted) { + goto out; + } + + ret =3D smmu_ptw(&cfg, addr, flag, &entry, &ptw_info); + if (ret) { + switch (ptw_info.type) { + case SMMU_PTW_ERR_WALK_EABT: + event.type =3D SMMU_EVT_F_WALK_EABT; + event.u.f_walk_eabt.addr =3D addr; + event.u.f_walk_eabt.rnw =3D flag & 0x1; + event.u.f_walk_eabt.class =3D 0x1; + event.u.f_walk_eabt.addr2 =3D ptw_info.addr; + break; + case SMMU_PTW_ERR_TRANSLATION: + if (event.record_trans_faults) { + event.type =3D SMMU_EVT_F_TRANSLATION; + event.u.f_translation.addr =3D addr; + event.u.f_translation.rnw =3D flag & 0x1; + } + break; + case SMMU_PTW_ERR_ADDR_SIZE: + if (event.record_trans_faults) { + event.type =3D SMMU_EVT_F_ADDR_SIZE; + event.u.f_addr_size.addr =3D addr; + event.u.f_addr_size.rnw =3D flag & 0x1; + } + break; + case SMMU_PTW_ERR_ACCESS: + if (event.record_trans_faults) { + event.type =3D SMMU_EVT_F_ACCESS; + event.u.f_access.addr =3D addr; + event.u.f_access.rnw =3D flag & 0x1; + } + break; + case SMMU_PTW_ERR_PERMISSION: + if (event.record_trans_faults) { + event.type =3D SMMU_EVT_F_PERMISSION; + event.u.f_permission.addr =3D addr; + event.u.f_permission.rnw =3D flag & 0x1; + } + break; + default: + error_setg(&error_fatal, "SMMUV3 BUG"); + } + } + + trace_smmuv3_translate(mr->parent_obj.name, sid, addr, + entry.translated_addr, entry.perm); +out: + if (ret) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s translation failed for iova=3D0x%"PRIx64" (%s)\n= ", + mr->parent_obj.name, addr, SMMU_EVENT_STRING(event.t= ype)); + entry.perm =3D IOMMU_NONE; + smmuv3_record_event(s, &event); + } else if (!cfg.aborted) { + entry.perm =3D flag; + } + + return entry; +} + static int smmuv3_cmdq_consume(SMMUv3State *s) { SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; @@ -739,6 +1077,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 c79c15e..1102bd4 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -29,3 +29,12 @@ smmuv3_write_mmio_idr(hwaddr addr, uint64_t val) "write = to RO/Unimpl reg 0x%lx v 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_record_event(const char *type, uint32_t sid) "%s sid=3D%d" +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) "%s sid=3D%d iova=3D0x%"PRIx64" translated=3D0x%"PRIx64" perm= =3D0x%x" +smmuv3_decode_cd(uint32_t oas) "oas=3D%d" +smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz= , int initial_level) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d, initial_= level =3D %d" --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518895527450563.676199935902; Sat, 17 Feb 2018 11:25:27 -0800 (PST) Received: from localhost ([::1]:49905 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en86w-0003eg-Dy for importer@patchew.org; Sat, 17 Feb 2018 14:25:26 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45140) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WO-0003dJ-PT for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:41 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WN-0002X1-Ct for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:40 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:56746 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WJ-00029t-IB; Sat, 17 Feb 2018 13:47:35 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0E5D98185322; Sat, 17 Feb 2018 18:47:35 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 70DEC2024CA2; Sat, 17 Feb 2018 18:47:32 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:52 +0100 Message-Id: <1518893216-9983-11-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 17 Feb 2018 18:47:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 17 Feb 2018 18:47:35 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 10/14] hw/arm/smmuv3: Abort on vfio or vhost case 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" At the moment, the SMMUv3 does not support notification on TLB invalidation. So let's abort as soon as such notifier gets enabled. Signed-off-by: Eric Auger --- hw/arm/smmuv3.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 384393f..5efe933 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1074,12 +1074,23 @@ static void smmuv3_class_init(ObjectClass *klass, v= oid *data) dc->realize =3D smmu_realize; } =20 +static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu, + IOMMUNotifierFlag old, + IOMMUNotifierFlag new) +{ + if (old =3D=3D IOMMU_NOTIFIER_NONE) { + error_setg(&error_fatal, + "SMMUV3: vhost and vfio notifiers not yet supported"); + } +} + static void smmuv3_iommu_memory_region_class_init(ObjectClass *klass, void *data) { 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 { --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518897096554469.2072358867438; Sat, 17 Feb 2018 11:51:36 -0800 (PST) Received: from localhost ([::1]:54872 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8WF-0003V0-Ql for importer@patchew.org; Sat, 17 Feb 2018 14:51:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45193) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7WR-0003g0-1H for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WP-0002jZ-U5 for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:43 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:42006 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WM-0002QY-Lj; Sat, 17 Feb 2018 13:47:38 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E3BC340FB639; Sat, 17 Feb 2018 18:47:37 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 524FB2024CA2; Sat, 17 Feb 2018 18:47:35 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:53 +0100 Message-Id: <1518893216-9983-12-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Sat, 17 Feb 2018 18:47:38 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Sat, 17 Feb 2018 18:47:38 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 11/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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 1219d00..9f5976a 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" @@ -666,6 +671,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 Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 15188972695211002.7481543010736; Sat, 17 Feb 2018 11:54:29 -0800 (PST) Received: from localhost ([::1]:55096 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8Z2-0005Zm-Pg for importer@patchew.org; Sat, 17 Feb 2018 14:54:28 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45316) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7Wa-0003n5-Si for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WY-0003WY-VS for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:52 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52370 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WP-0002fy-Bb; Sat, 17 Feb 2018 13:47:41 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C96C3402242D; Sat, 17 Feb 2018 18:47:40 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 33C1B2024CA2; Sat, 17 Feb 2018 18:47:38 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:54 +0100 Message-Id: <1518893216-9983-13-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 17 Feb 2018 18:47:40 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 17 Feb 2018 18:47:40 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 12/14] hw/arm/virt: Add SMMUv3 to the virt board 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prem Mallappa Add code to instantiate an smmuv3 in virt machine. A new iommu integer member is introduced in VirtMachineState to store the type of the iommu in use. Signed-off-by: Prem Mallappa Signed-off-by: Eric Auger Reviewed-by: Peter Maydell --- v7 -> v8: - integer iommu member - add primary-bus property v4 -> v5: - add dma-coherent property v2 -> v3: - vbi was removed. Use vms instead - migrate to new smmu binding format (iommu-map) - don't use appendprop anymore - add vms->smmu and guard instantiation with this latter - interrupts type changed to edge Conflicts: hw/arm/smmuv3.c --- hw/arm/virt.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++= +++- include/hw/arm/virt.h | 10 ++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index dbb3c80..e9dca0d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -58,6 +58,7 @@ #include "hw/smbios/smbios.h" #include "qapi/visitor.h" #include "standard-headers/linux/input.h" +#include "hw/arm/smmuv3.h" =20 #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ @@ -141,6 +142,7 @@ static const MemMapEntry a15memmap[] =3D { [VIRT_FW_CFG] =3D { 0x09020000, 0x00000018 }, [VIRT_GPIO] =3D { 0x09030000, 0x00001000 }, [VIRT_SECURE_UART] =3D { 0x09040000, 0x00001000 }, + [VIRT_SMMU] =3D { 0x09050000, 0x00020000 }, /* 128K, nee= ded */ [VIRT_MMIO] =3D { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that siz= e */ [VIRT_PLATFORM_BUS] =3D { 0x0c000000, 0x02000000 }, @@ -161,6 +163,7 @@ static const int a15irqmap[] =3D { [VIRT_SECURE_UART] =3D 8, [VIRT_MMIO] =3D 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ [VIRT_GIC_V2M] =3D 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ + [VIRT_SMMU] =3D 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ [VIRT_PLATFORM_BUS] =3D 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */ }; =20 @@ -941,7 +944,57 @@ 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_smmu(const VirtMachineState *vms, qemu_irq *pic, + PCIBus *bus) +{ + char *node; + const char compat[] =3D "arm,smmu-v3"; + int irq =3D vms->irqmap[VIRT_SMMU]; + int i; + hwaddr base =3D vms->memmap[VIRT_SMMU].base; + hwaddr size =3D vms->memmap[VIRT_SMMU].size; + const char irq_names[] =3D "eventq\0priq\0cmdq-sync\0gerror"; + DeviceState *dev; + + if (vms->iommu !=3D VIRT_IOMMU_SMMUV3 || !vms->iommu_phandle) { + return; + } + + dev =3D qdev_create(NULL, "arm-smmuv3"); + + object_property_set_link(OBJECT(dev), OBJECT(bus), "primary-bus", + &error_abort); + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + for (i =3D 0; i < NUM_SMMU_IRQS; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); + } + + node =3D g_strdup_printf("/smmuv3@%" PRIx64, base); + qemu_fdt_add_subnode(vms->fdt, node); + qemu_fdt_setprop(vms->fdt, node, "compatible", compat, sizeof(compat)); + qemu_fdt_setprop_sized_cells(vms->fdt, node, "reg", 2, base, 2, size); + + qemu_fdt_setprop_cells(vms->fdt, node, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irq , GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, + GIC_FDT_IRQ_TYPE_SPI, irq + 1, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, + GIC_FDT_IRQ_TYPE_SPI, irq + 2, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI, + GIC_FDT_IRQ_TYPE_SPI, irq + 3, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); + + qemu_fdt_setprop(vms->fdt, node, "interrupt-names", irq_names, + sizeof(irq_names)); + + qemu_fdt_setprop_cell(vms->fdt, node, "clocks", vms->clock_phandle); + qemu_fdt_setprop_string(vms->fdt, node, "clock-names", "apb_pclk"); + qemu_fdt_setprop(vms->fdt, node, "dma-coherent", NULL, 0); + + qemu_fdt_setprop_cell(vms->fdt, node, "#iommu-cells", 1); + + qemu_fdt_setprop_cell(vms->fdt, node, "phandle", vms->iommu_phandle); + g_free(node); +} + +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; @@ -1054,6 +1107,15 @@ static void create_pcie(const VirtMachineState *vms,= qemu_irq *pic) qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1); create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename); =20 + if (vms->iommu) { + vms->iommu_phandle =3D qemu_fdt_alloc_phandle(vms->fdt); + + create_smmu(vms, pic, pci->bus); + + qemu_fdt_setprop_cells(vms->fdt, nodename, "iommu-map", + 0x0, vms->iommu_phandle, 0x0, 0x10000); + } + g_free(nodename); } =20 diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 33b0ff3..13d3724 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -38,6 +38,7 @@ =20 #define NUM_GICV2M_SPIS 64 #define NUM_VIRTIO_TRANSPORTS 32 +#define NUM_SMMU_IRQS 4 =20 #define ARCH_GICV3_MAINT_IRQ 9 =20 @@ -59,6 +60,7 @@ enum { VIRT_GIC_V2M, VIRT_GIC_ITS, VIRT_GIC_REDIST, + VIRT_SMMU, VIRT_UART, VIRT_MMIO, VIRT_RTC, @@ -74,6 +76,12 @@ enum { VIRT_SECURE_MEM, }; =20 +enum { + VIRT_IOMMU_NONE, + VIRT_IOMMU_SMMUV3, + VIRT_IOMMU_VIRTIO, +}; + typedef struct MemMapEntry { hwaddr base; hwaddr size; @@ -96,6 +104,7 @@ typedef struct { bool its; bool virt; int32_t gic_version; + int32_t iommu; struct arm_boot_info bootinfo; const MemMapEntry *memmap; const int *irqmap; @@ -105,6 +114,7 @@ typedef struct { uint32_t clock_phandle; uint32_t gic_phandle; uint32_t msi_phandle; + uint32_t iommu_phandle; int psci_conduit; } VirtMachineState; =20 --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518897356851551.9021920639161; Sat, 17 Feb 2018 11:55:56 -0800 (PST) Received: from localhost ([::1]:55209 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8aL-0006ZY-Mh for importer@patchew.org; Sat, 17 Feb 2018 14:55:49 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45319) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7Wb-0003nH-1o for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:56 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WY-0003WM-Ud for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:53 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:51834 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WS-0002vb-8m; Sat, 17 Feb 2018 13:47:44 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A6FD7406FA3F; Sat, 17 Feb 2018 18:47:43 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id 193572024CA2; Sat, 17 Feb 2018 18:47:40 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:55 +0100 Message-Id: <1518893216-9983-14-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Sat, 17 Feb 2018 18:47:43 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Sat, 17 Feb 2018 18:47:43 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 13/14] 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Prem Mallappa This patch builds the smmuv3 node in the ACPI IORT table. 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. The guest must feature the IOMMU probe deferral series (https://lkml.org/lkml/2017/4/10/214) which fixes streamid multiple lookup. This bug is not related to the SMMU emulation. Signed-off-by: Prem Mallappa Signed-off-by: Eric Auger --- 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/virt-acpi-build.c | 56 +++++++++++++++++++++++++++++++++++++++--= ---- include/hw/acpi/acpi-defs.h | 15 ++++++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index f7fa795..4b5ad91 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -393,19 +393,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->iommu) { + 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 +425,35 @@ 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->iommu =3D=3D VIRT_IOMMU_SMMUV3) { + int irq =3D vms->irqmap[VIRT_SMMU]; + + /* 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->memmap[VIRT_SMMU].base); + smmu->event_gsiv =3D cpu_to_le32(irq); + smmu->pri_gsiv =3D cpu_to_le32(irq + 1); + smmu->gerr_gsiv =3D cpu_to_le32(irq + 2); + smmu->sync_gsiv =3D cpu_to_le32(irq + 3); + + /* 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 +474,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->iommu) { + /* 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 @@ -786,7 +828,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 80c8099..068ce28 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -700,6 +700,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; --=20 2.5.5 From nobody Thu Dec 18 13:15:22 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1518896435911261.07453184067106; Sat, 17 Feb 2018 11:40:35 -0800 (PST) Received: from localhost ([::1]:52575 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en8Lb-0001dt-1a for importer@patchew.org; Sat, 17 Feb 2018 14:40:35 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45314) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1en7Wa-0003ld-I8 for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1en7WZ-0003X3-0j for qemu-devel@nongnu.org; Sat, 17 Feb 2018 13:47:52 -0500 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:43752 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1en7WV-0003BC-33; Sat, 17 Feb 2018 13:47:47 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 89E63857A1; Sat, 17 Feb 2018 18:47:46 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-21.ams2.redhat.com [10.36.116.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id EAC942024CA2; Sat, 17 Feb 2018 18:47:43 +0000 (UTC) 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: Sat, 17 Feb 2018 19:46:56 +0100 Message-Id: <1518893216-9983-15-git-send-email-eric.auger@redhat.com> In-Reply-To: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> References: <1518893216-9983-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 17 Feb 2018 18:47:46 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 17 Feb 2018 18:47:46 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v9 14/14] hw/arm/virt: Handle iommu in 2.12 machine type 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: mst@redhat.com, jean-philippe.brucker@arm.com, tn@semihalf.com, peterx@redhat.com, edgar.iglesias@gmail.com, linuc.decode@gmail.com, bharat.bhushan@nxp.com, christoffer.dall@linaro.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The new machine type exposes a new "iommu" virt machine option. The SMMUv3 IOMMU is instantiated using -machine virt,iommu=3Dsmmuv3. Signed-off-by: Eric Auger --- v7 -> v8: - Revert to machine option, now dubbed "iommu", preparing for virtio instantiation. v5 -> v6: machine 2_11 Another alternative would be to use the -device option as done on x86. As the smmu is a sysbus device, we would need to use the platform bus framework. --- hw/arm/virt.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ include/hw/arm/virt.h | 1 + 2 files changed, 46 insertions(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index e9dca0d..607c7e1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1547,6 +1547,34 @@ static void virt_set_gic_version(Object *obj, const = char *value, Error **errp) } } =20 +static char *virt_get_iommu(Object *obj, Error **errp) +{ + VirtMachineState *vms =3D VIRT_MACHINE(obj); + + switch (vms->iommu) { + case VIRT_IOMMU_NONE: + return g_strdup("none"); + case VIRT_IOMMU_SMMUV3: + return g_strdup("smmuv3"); + default: + return g_strdup("none"); + } +} + +static void virt_set_iommu(Object *obj, const char *value, Error **errp) +{ + VirtMachineState *vms =3D VIRT_MACHINE(obj); + + if (!strcmp(value, "smmuv3")) { + vms->iommu =3D VIRT_IOMMU_SMMUV3; + } else if (!strcmp(value, "none")) { + vms->iommu =3D VIRT_IOMMU_NONE; + } else { + error_setg(errp, "Invalid iommu value"); + error_append_hint(errp, "Valid value are none, smmuv3\n"); + } +} + static CpuInstanceProperties virt_cpu_index_to_props(MachineState *ms, unsigned cpu_index) { @@ -1679,6 +1707,19 @@ static void virt_2_12_instance_init(Object *obj) NULL); } =20 + if (vmc->no_iommu) { + vms->iommu =3D VIRT_IOMMU_NONE; + } else { + /* Default disallows smmu instantiation */ + vms->iommu =3D VIRT_IOMMU_NONE; + object_property_add_str(obj, "iommu", virt_get_iommu, + virt_set_iommu, NULL); + object_property_set_description(obj, "iommu", + "Set the IOMMU model among " + "none, smmuv3 (default none)", + NULL); + } + vms->memmap =3D a15memmap; vms->irqmap =3D a15irqmap; } @@ -1698,8 +1739,12 @@ static void virt_2_11_instance_init(Object *obj) =20 static void virt_machine_2_11_options(MachineClass *mc) { + VirtMachineClass *vmc =3D VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_2_12_options(mc); SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_11); + + vmc->no_iommu =3D true; } DEFINE_VIRT_MACHINE(2, 11) =20 diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 13d3724..3a92fc3 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -92,6 +92,7 @@ typedef struct { bool disallow_affinity_adjustment; bool no_its; bool no_pmu; + bool no_iommu; bool claim_edge_triggered_timers; } VirtMachineClass; =20 --=20 2.5.5