From nobody Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838139258211.42386265730318; Mon, 5 Feb 2018 05:42:19 -0800 (PST) Received: from localhost ([::1]:45021 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih2I-0005ot-Ct for importer@patchew.org; Mon, 05 Feb 2018 08:42:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50811) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih0Z-0004tb-21 for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:40:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih0W-0005Ku-0m for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:40:29 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52142) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih0P-0005Eq-Ac; Mon, 05 Feb 2018 08:40:21 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 409232820C; Mon, 5 Feb 2018 13:40:20 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id A9A6B177C3; Mon, 5 Feb 2018 13:39:55 +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: Mon, 5 Feb 2018 14:39:19 +0100 Message-Id: <1517837972-1904-2-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 05 Feb 2018 13:40:20 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 | 71 ++++++++++++++++++++ include/hw/arm/smmu-common.h | 126 ++++++++++++++++++++++++++++++++= ++++ 4 files changed, 199 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..c2f6b15 --- /dev/null +++ b/hw/arm/smmu-common.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2014-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U= SA. + * + * Author: Prem Mallappa + * + */ + +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "exec/address-spaces.h" +#include "trace.h" +#include "exec/target_page.h" +#include "qom/cpu.h" +#include "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) +{ +} + +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; +} + +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..0f9af40 --- /dev/null +++ b/include/hw/arm/smmu-common.h @@ -0,0 +1,126 @@ +/* + * ARM SMMU Support + * + * Copyright (C) 2015-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMU_COMMON_H +#define HW_ARM_SMMU_COMMON_H + +#include +#include "hw/pci/pci.h" + +#define SMMU_PCI_BUS_MAX 256 +#define SMMU_PCI_DEVFN_MAX 256 + +#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 */ + 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; + 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 int (*smmu_page_walk_hook)(IOMMUTLBEntry *entry, void *private); + +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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838268192826.5520286343774; Mon, 5 Feb 2018 05:44:28 -0800 (PST) Received: from localhost ([::1]:45146 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih4N-0007gt-Aq for importer@patchew.org; Mon, 05 Feb 2018 08:44:27 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50887) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih0t-00057s-Cv for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:40:52 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih0r-0005ex-Tk for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:40:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41234) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih0l-0005Wk-20; Mon, 05 Feb 2018 08:40:43 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 43696883BC; Mon, 5 Feb 2018 13:40:42 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 95EFE5F70E; Mon, 5 Feb 2018 13:40: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: Mon, 5 Feb 2018 14:39:20 +0100 Message-Id: <1517837972-1904-3-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 05 Feb 2018 13:40:42 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 | 61 ++++++++++++++++++++++++++++++++++++++++= ++++ include/hw/arm/smmu-common.h | 6 +++++ 2 files changed, 67 insertions(+) diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index c2f6b15..7bf8e57 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -32,8 +32,69 @@ #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); + + 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 Property smmu_dev_properties[] =3D { diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 0f9af40..1495bce 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -123,4 +123,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838501513788.3280522732006; Mon, 5 Feb 2018 05:48:21 -0800 (PST) Received: from localhost ([::1]:45222 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih88-0002No-Lc for importer@patchew.org; Mon, 05 Feb 2018 08:48:20 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50995) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih1E-0005RQ-PX for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:41:15 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih19-0005xe-Pk for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:41:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:58438) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih14-0005sx-To; Mon, 05 Feb 2018 08:41:03 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 188EBC0587E1; Mon, 5 Feb 2018 13:41:02 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 96F7C17558; Mon, 5 Feb 2018 13:40:42 +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: Mon, 5 Feb 2018 14:39:21 +0100 Message-Id: <1517837972-1904-4-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 05 Feb 2018 13:41:02 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 | 220 +++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/smmu-internal.h | 104 ++++++++++++++++++++ hw/arm/trace-events | 12 +++ include/hw/arm/smmu-common.h | 6 ++ 4 files changed, 342 insertions(+) create mode 100644 hw/arm/smmu-internal.h diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index 7bf8e57..cb1855f 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -31,6 +31,226 @@ =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) { + qemu_log_mask(LOG_GUEST_ERROR, + "Cannot fetch pte at address=3D0x%"PRIx64"\n", addr); + 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 */ + +#define PTE_ADDRESS(pte, shift) (extract64(pte, shift, 47 - shift) << shif= t) + +/** + * get_page_pte_address - returns the L3 descriptor output address, + * ie. the page frame + * ARM ARM spec: Figure D4-17 VMSAv8-64 level 3 descriptor format + */ +static inline hwaddr get_page_pte_address(uint64_t pte, int granule_sz) +{ + return PTE_ADDRESS(pte, granule_sz); +} + +/** + * get_table_pte_address - return table descriptor output address, + * ie. address of next level table + * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor f= ormats + */ +static inline hwaddr get_table_pte_address(uint64_t pte, int granule_sz) +{ + return PTE_ADDRESS(pte, granule_sz); +} + +/** + * get_block_pte_address - return block descriptor output address and bloc= k size + * ARM ARM Figure D4-16 VMSAv8-64 level0, level1, and level 2 descriptor f= ormats + */ +static hwaddr get_block_pte_address(uint64_t pte, int level, int granule_s= z, + uint64_t *bsz) +{ + int n =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 + * @tlbe: pre-filled IOMMUTLBEntry + * @info: handle to an error info + * + * Return 0 on success, < 0 on error. In case of error @info is filled + */ +static int smmu_ptw_64(SMMUTransCfg *cfg, IOMMUTLBEntry *tlbe, + SMMUPTWEventInfo *info) +{ + dma_addr_t baseaddr; + int stage =3D cfg->stage; + dma_addr_t iova =3D tlbe->iova; + 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->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); + + trace_smmu_page_walk_level(level, iova, subpage_size, + baseaddr, offset, pte); + + if (get_pte(baseaddr, offset, &pte, info)) { + info->type =3D SMMU_PTW_ERR_WALK_EABT; + info->addr =3D pte_addr; + goto error; + } + if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) { + trace_smmu_page_walk_level_res_invalid_pte(stage, level, basea= ddr, + pte_addr, offset, p= te); + 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); + if (is_fault(tlbe->perm, pte, true)) { + info->type =3D SMMU_PTW_ERR_PERMISSION; + goto error; + } + + tlbe->translated_addr =3D gpa + (iova & mask); + trace_smmu_page_walk_level_page_pte(stage, level, iova, + baseaddr, pte_addr, pte, g= pa); + 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); + if (is_fault(tlbe->perm, pte, true)) { + info->type =3D SMMU_PTW_ERR_PERMISSION; + goto error; + } + + trace_smmu_page_walk_level_block_pte(stage, level, baseaddr, + pte_addr, pte, iova, gpa, + (int)(block_size >> 20)); + + tlbe->translated_addr =3D gpa + (iova & mask); + return 0; + } + + /* table pte */ + if (is_fault(tlbe->perm, pte, false)) { + 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: + return -EINVAL; +} + +/** + * smmu_ptw - Walk the page tables for an IOVA, according to @cfg + * + * @cfg: translation configuration + * @tlbe: pre-filled entry + * @info: ptw event handle + * + * return 0 on success + */ +int smmu_ptw(SMMUTransCfg *cfg, 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, 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..7dd3a53 --- /dev/null +++ b/hw/arm/smmu-internal.h @@ -0,0 +1,104 @@ +/* + * ARM SMMU support - Internal API + * + * Copyright (c) 2017 Red Hat, Inc. + * Written by Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMU_INTERNAL_H +#define HW_ARM_SMMU_INTERNAL_H + +#define ARM_LPAE_MAX_ADDR_BITS 48 +#define ARM_LPAE_MAX_LEVELS 4 + +/* PTE Manipulation */ + +#define ARM_LPAE_PTE_TYPE_SHIFT 0 +#define ARM_LPAE_PTE_TYPE_MASK 0x3 + +#define ARM_LPAE_PTE_TYPE_BLOCK 1 +#define ARM_LPAE_PTE_TYPE_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) + +static inline bool is_invalid_pte(uint64_t pte) +{ + return !(pte & ARM_LPAE_PTE_VALID); +} + +static inline bool is_reserved_pte(uint64_t pte, int level) +{ + return (level =3D=3D 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_L3_PTE_TYPE_RE= SERVED); +} + +static inline bool is_block_pte(uint64_t pte, int level) +{ + return (level < 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_BLOCK= ); +} + +static inline bool is_table_pte(uint64_t pte, int level) +{ + return (level < 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_PTE_TYPE_TABLE= ); +} + +static inline bool is_page_pte(uint64_t pte, int level) +{ + return (level =3D=3D 3) && + ((pte & ARM_LPAE_PTE_TYPE_MASK) =3D=3D ARM_LPAE_L3_PTE_TYPE_PA= GE); +} + +static inline bool is_fault(int perm, uint64_t pte, bool leaf) +{ + uint64_t ap; /* AP or APTable */ + + if (leaf) { + ap =3D extract64(pte, 6, 2); + } else { + ap =3D extract64(pte, 61, 2); + } + return (perm & IOMMU_WO) && (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..c67cd39 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -2,3 +2,15 @@ =20 # hw/arm/virt-acpi-build.c virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out." + +# hw/arm/smmu-common.c + +smmu_page_walk(int stage, uint64_t baseaddr, int first_level, uint64_t sta= rt, uint64_t end) "stage=3D%d, baseaddr=3D0x%"PRIx64", first level=3D%d, st= art=3D0x%"PRIx64", end=3D0x%"PRIx64 +smmu_page_walk_level_in(int level, uint64_t baseaddr, int granule_sz, uint= 64_t start, uint64_t end, int flags, uint64_t subpage_size) "level=3D%d bas= eaddr=3D0x%"PRIx64" granule=3D%d, start=3D0x%"PRIx64" end=3D0x%"PRIx64" fla= gs=3D%d subpage_size=3D0x%lx" +smmu_page_walk_level(int level, uint64_t iova, size_t subpage_size, uint64= _t baseaddr, uint32_t offset, uint64_t pte) "level=3D%d iova=3D0x%lx subpag= e_sz=3D0x%lx baseaddr=3D0x%"PRIx64" offset=3D%d =3D> pte=3D0x%lx" +smmu_page_walk_level_res_invalid_pte(int stage, int level, uint64_t basead= dr, uint64_t pteaddr, uint32_t offset, uint64_t pte) "stage=3D%d level=3D%d= base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" offset=3D%d pte=3D0x%lx" +smmu_page_walk_level_page_pte(int stage, int level, uint64_t iova, uint64= _t baseaddr, uint64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d = level=3D%d iova=3D0x%"PRIx64" base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D= 0x%"PRIx64" page address =3D 0x%"PRIx64 +smmu_page_walk_level_block_pte(int stage, int level, uint64_t baseaddr, ui= nt64_t pteaddr, uint64_t pte, uint64_t iova, uint64_t gpa, int bsize_mb) "s= tage=3D%d level=3D%d base@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx6= 4" iova=3D0x%"PRIx64" block address =3D 0x%"PRIx64" block size =3D %d MiB" +smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, ui= nt64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d, level=3D%d bas= e@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" next table address = =3D 0x%"PRIx64 +smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte)= "baseaddr=3D0x%"PRIx64" index=3D0x%x, pteaddr=3D0x%"PRIx64", pte=3D0x%"PRI= x64 +smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova =3D 0x%"PRIx64" = -> pa =3D 0x%"PRIx64 diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h index 1495bce..e29ea00 100644 --- a/include/hw/arm/smmu-common.h +++ b/include/hw/arm/smmu-common.h @@ -129,4 +129,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, IOMMUTLBEntry *tlbe, + SMMUPTWEventInfo *info); + +SMMUTransTableInfo *select_tt(SMMUTransCfg *cfg, dma_addr_t iova); + #endif /* HW_ARM_SMMU_COMMON */ --=20 2.5.5 From nobody Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838727933808.433536500202; Mon, 5 Feb 2018 05:52:07 -0800 (PST) Received: from localhost ([::1]:45352 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihBn-0005bA-0z for importer@patchew.org; Mon, 05 Feb 2018 08:52:07 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51077) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih1b-0005gn-6O for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:41:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih1Y-0006NV-Gd for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:41:35 -0500 Received: from mx1.redhat.com ([209.132.183.28]:51744) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih1Q-0006Ev-Cp; Mon, 05 Feb 2018 08:41:24 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8613578540; Mon, 5 Feb 2018 13:41:23 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6E99E17558; Mon, 5 Feb 2018 13:41:02 +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: Mon, 5 Feb 2018 14:39:22 +0100 Message-Id: <1517837972-1904-5-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 05 Feb 2018 13:41:23 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 | 344 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 3 + include/hw/arm/smmuv3.h | 91 +++++++++++++ 5 files changed, 594 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..84a15c1 --- /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 as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMU_V3_INTERNAL_H +#define HW_ARM_SMMU_V3_INTERNAL_H + +#include "trace.h" +#include "qemu/error-report.h" +#include "hw/arm/smmu-common.h" + +/* MMIO 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..c9a13b0 --- /dev/null +++ b/hw/arm/smmuv3.c @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2014-2016 Broadcom Corporation + * Copyright (c) 2017 Red Hat, Inc. + * Written by Prem Mallappa, Eric Auger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "hw/boards.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "hw/pci/pci.h" +#include "exec/address-spaces.h" +#include "trace.h" +#include "qemu/error-report.h" +#include "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); + 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->reset =3D smmu_reset; + dc->vmsd =3D &vmstate_smmuv3; + 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 c67cd39..8affbf7 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -14,3 +14,6 @@ smmu_page_walk_level_block_pte(int stage, int level, uint= 64_t baseaddr, uint64_t smmu_page_walk_level_table_pte(int stage, int level, uint64_t baseaddr, ui= nt64_t pteaddr, uint64_t pte, uint64_t address) "stage=3D%d, level=3D%d bas= e@=3D0x%"PRIx64" pte@=3D0x%"PRIx64" pte=3D0x%"PRIx64" next table address = =3D 0x%"PRIx64 smmu_get_pte(uint64_t baseaddr, int index, uint64_t pteaddr, uint64_t pte)= "baseaddr=3D0x%"PRIx64" index=3D0x%x, pteaddr=3D0x%"PRIx64", pte=3D0x%"PRI= x64 smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova =3D 0x%"PRIx64" = -> pa =3D 0x%"PRIx64 + +#hw/arm/smmuv3.c +smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx= 64" val:0x%"PRIx64" size: 0x%x" diff --git a/include/hw/arm/smmuv3.h b/include/hw/arm/smmuv3.h new file mode 100644 index 0000000..1d4e50e --- /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 as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef HW_ARM_SMMUV3_H +#define HW_ARM_SMMUV3_H + +#include "hw/arm/smmu-common.h" +#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; +} 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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838258970550.0538184018814; Mon, 5 Feb 2018 05:44:18 -0800 (PST) Received: from localhost ([::1]:45140 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih4A-0007WU-BB for importer@patchew.org; Mon, 05 Feb 2018 08:44:14 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51199) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih1x-0005wv-FR for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih1w-0006l6-G1 for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:41:57 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52172) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih1l-0006Z6-1v; Mon, 05 Feb 2018 08:41:45 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 25F98C001F16; Mon, 5 Feb 2018 13:41:44 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id DB46017558; Mon, 5 Feb 2018 13:41: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: Mon, 5 Feb 2018 14:39:23 +0100 Message-Id: <1517837972-1904-6-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 05 Feb 2018 13:41:44 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 84a15c1..72d9c6c 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 c9a13b0..6bad7e8 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 8affbf7..957a67e 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -17,3 +17,6 @@ smmu_set_translated_address(hwaddr iova, hwaddr pa) "iova= =3D 0x%"PRIx64" -> pa =3D =20 #hw/arm/smmuv3.c smmuv3_read_mmio(hwaddr addr, uint64_t val, unsigned size) "addr: 0x%"PRIx= 64" val:0x%"PRIx64" size: 0x%x" +smmuv3_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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838311083845.3038583520105; Mon, 5 Feb 2018 05:45:11 -0800 (PST) Received: from localhost ([::1]:45161 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih54-0008JE-7R for importer@patchew.org; Mon, 05 Feb 2018 08:45:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51209) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih1y-0005zi-G1 for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:02 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih1t-0006hc-Lp for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:41:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41902) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih1p-0006cX-4G; Mon, 05 Feb 2018 08:41:49 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3F3268765E; Mon, 5 Feb 2018 13:41:48 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7B4D017240; Mon, 5 Feb 2018 13:41:44 +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: Mon, 5 Feb 2018 14:39:24 +0100 Message-Id: <1517837972-1904-7-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 05 Feb 2018 13:41:48 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- v7 -> v8 - use address_space_rw - helpers inspired from spec --- hw/arm/smmuv3-internal.h | 142 ++++++++++++++++++++++++++++++++++++++++++++ hw/arm/smmuv3.c | 151 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 4 ++ 3 files changed, 297 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 72d9c6c..44564ed 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -162,4 +162,146 @@ 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 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", +}; + +/* CMDQ fields */ + +typedef enum { + SMMU_CERROR_NONE =3D 0, + SMMU_CERROR_ILL, + SMMU_CERROR_ABT, + SMMU_CERROR_ATC_INV_SYNC, +} SMMUCmdError; + +enum { /* Command completion notification */ + CMD_SYNC_SIG_NONE, + CMD_SYNC_SIG_IRQ, + CMD_SYNC_SIG_SEV, +}; + +#define CMD_TYPE(x) extract32((x)->word[0], 0, 8) +#define CMD_SEC(x) extract32((x)->word[0], 9, 1) +#define CMD_SEV(x) extract32((x)->word[0], 10, 1) +#define CMD_AC(x) extract32((x)->word[0], 12, 1) +#define CMD_AB(x) extract32((x)->word[0], 13, 1) +#define CMD_CS(x) extract32((x)->word[0], 12, 2) +#define CMD_SSID(x) extract32((x)->word[0], 16, 16) +#define CMD_SID(x) ((x)->word[1]) +#define CMD_VMID(x) extract32((x)->word[1], 0, 16) +#define CMD_ASID(x) extract32((x)->word[1], 16, 16) +#define CMD_STAG(x) extract32((x)->word[2], 0, 16) +#define CMD_RESP(x) extract32((x)->word[2], 11, 2) +#define CMD_GRPID(x) extract32((x)->word[3], 0, 8) +#define CMD_SIZE(x) extract32((x)->word[3], 0, 16) +#define CMD_LEAF(x) extract32((x)->word[3], 0, 1) +#define CMD_SPAN(x) extract32((x)->word[3], 0, 5) +#define CMD_ADDR(x) ({ \ + uint64_t addr =3D (uint64_t)(x)->word[3]; \ + addr <<=3D 32; \ + addr |=3D extract32((x)->word[3], 12, 20); \ + addr; \ + }) + +int smmuv3_cmdq_consume(SMMUv3State *s); + #endif diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 6bad7e8..79970d7 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -94,6 +94,75 @@ 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 MemTxResult smmu_queue_read(SMMUQueue *q, void *data) +{ + dma_addr_t addr =3D Q_CONS_ENTRY(q); + MemTxResult ret; + + ret =3D dma_memory_read(&address_space_memory, addr, + (uint8_t *)data, q->entry_size); + if (ret !=3D MEMTX_OK) { + return ret; + } + + q->cons =3D queue_index_inc(q->cons, INDEX_MASK(q), WRAP_MASK(q)); + return ret; +} + +static void smmu_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; + } + + q->prod =3D queue_index_inc(q->prod, INDEX_MASK(q), WRAP_MASK(q)); +} + +static inline MemTxResult smmuv3_read_cmdq(SMMUv3State *s, Cmd *cmd) +{ + SMMUQueue *q =3D &s->cmdq; + return smmu_queue_read(q, cmd); +} + +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; + } + + smmu_queue_write(q, evt); + + if (q_empty) { + smmuv3_trigger_irq(s, SMMU_IRQ_EVTQ, 0); + } +} + static void smmuv3_init_regs(SMMUv3State *s) { /** @@ -133,6 +202,88 @@ 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; + + + if (!SMMUV3_CMDQ_ENABLED(s)) { + return 0; + } + + while (!Q_EMPTY(q)) { + uint32_t pending =3D s->gerror ^ s->gerrorn; + uint32_t type; + 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 (smmuv3_read_cmdq(s, &cmd) !=3D MEMTX_OK) { + cmd_error =3D SMMU_CERROR_ABT; + break; + } + + type =3D CMD_TYPE(&cmd); + + switch (type) { + case SMMU_CMD_SYNC: + if (CMD_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 (type !=3D SMMU_CERROR_ILL) { + trace_smmuv3_cmdq_opcode(cmd_stringify[type]); + } + } + + if (cmd_error) { + error_report("GERROR_CMDQ: CONS.ERR=3D%d", 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 957a67e..d73e151 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -20,3 +20,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1517838456603883.728647612406; Mon, 5 Feb 2018 05:47:36 -0800 (PST) Received: from localhost ([::1]:45220 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih7K-0001n3-EP for importer@patchew.org; Mon, 05 Feb 2018 08:47:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51319) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih2C-0006BA-RW for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih27-0006wp-VF for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52448) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih24-0006sm-MS; Mon, 05 Feb 2018 08:42:04 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C8F7EC047B94; Mon, 5 Feb 2018 13:42:03 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 920EA17240; Mon, 5 Feb 2018 13:41:48 +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: Mon, 5 Feb 2018 14:39:25 +0100 Message-Id: <1517837972-1904-8-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 05 Feb 2018 13:42:03 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 44564ed..799bce0 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) @@ -302,6 +318,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 79970d7..8e9eab2 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; @@ -202,7 +203,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; @@ -287,7 +288,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 d73e151..8a4acb9 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -24,3 +24,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838529061218.72816624340408; Mon, 5 Feb 2018 05:48:49 -0800 (PST) Received: from localhost ([::1]:45223 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih8a-0002lJ-9E for importer@patchew.org; Mon, 05 Feb 2018 08:48:48 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51383) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih2N-0006LM-OG for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih2I-000785-Pn for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52524) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih29-0006xm-66; Mon, 05 Feb 2018 08:42:09 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 51D60C001F17; Mon, 5 Feb 2018 13:42:08 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2B37017240; Mon, 5 Feb 2018 13:42:03 +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: Mon, 5 Feb 2018 14:39:26 +0100 Message-Id: <1517837972-1904-9-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 05 Feb 2018 13:42:08 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 | 136 +++++++++++++++++++++++++++++++++++++++++++= +++- hw/arm/smmuv3.c | 91 ++++++++++++++++++++++++++++++- hw/arm/trace-events | 1 + 3 files changed, 225 insertions(+), 3 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 799bce0..2ed7f1e 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -220,8 +220,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 { @@ -318,4 +316,138 @@ 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", +}; + +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 8e9eab2..a90468d 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -143,7 +143,7 @@ static inline MemTxResult smmuv3_read_cmdq(SMMUv3State = *s, Cmd *cmd) return smmu_queue_read(q, cmd); } =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); @@ -164,6 +164,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(event_stringify[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 8a4acb9..f6757c1 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -30,3 +30,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838956707552.9199809121037; Mon, 5 Feb 2018 05:55:56 -0800 (PST) Received: from localhost ([::1]:45447 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihFT-0000T1-P9 for importer@patchew.org; Mon, 05 Feb 2018 08:55:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51449) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih2a-0006W7-Pm for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih2Y-0007Nc-TF for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:36 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42232) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih2R-0007FD-6V; Mon, 05 Feb 2018 08:42:27 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5317687623; Mon, 5 Feb 2018 13:42:26 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id A688117240; Mon, 5 Feb 2018 13:42:08 +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: Mon, 5 Feb 2018 14:39:27 +0100 Message-Id: <1517837972-1904-10-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 05 Feb 2018 13:42:26 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 | 326 +++++++++++++++++++++++++++++++++++++++++++= ++++ hw/arm/trace-events | 9 ++ 3 files changed, 481 insertions(+) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index 2ed7f1e..853dd93 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -450,4 +450,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 a90468d..da05d47 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -292,6 +292,329 @@ 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); + 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); + 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)= ); + ret =3D dma_memory_read(&address_space_memory, l1ptr, + (uint8_t *)&l1std, sizeof(l1std)); + if (ret !=3D MEMTX_OK) { + error_report("Could not read L1PTR at 0X%"PRIx64, 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 */ + error_report("invalid sid=3D%d (L1STD span=3D0)", 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) { + error_report("l2_ste_offset=3D%d > max_l2_ste=3D%d", + 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); + + 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; + uint16_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 flag, + }; + + if (!smmu_enabled(s)) { + goto out; + } + + if (smmuv3_decode_config(mr, &cfg, &event)) { + goto out; + } + + if (smmu_ptw(&cfg, &entry, &ptw_info)) { + 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 (event.type) { + error_report("%s translation failed for iova=3D0x%"PRIx64" (%s)", + mr->parent_obj.name, addr, event_stringify[event.type= ]); + entry.perm =3D IOMMU_NONE; + smmuv3_record_event(s, &event); + } + if (cfg.aborted) { + entry.perm =3D IOMMU_NONE; + } + return entry; +} + static int smmuv3_cmdq_consume(SMMUv3State *s) { SMMUCmdError cmd_error =3D SMMU_CERROR_NONE; @@ -724,6 +1047,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 f6757c1..ec335c1 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -31,3 +31,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838680600882.3542834117213; Mon, 5 Feb 2018 05:51:20 -0800 (PST) Received: from localhost ([::1]:45299 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihB1-0004vq-NK for importer@patchew.org; Mon, 05 Feb 2018 08:51:19 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51478) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih2i-0006bM-6u for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih2d-0007S5-IX for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:42:44 -0500 Received: from mx1.redhat.com ([209.132.183.28]:55934) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih2V-0007JC-5Y; Mon, 05 Feb 2018 08:42:31 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 42EB778238; Mon, 5 Feb 2018 13:42:30 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id AA10A17240; Mon, 5 Feb 2018 13:42: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: Mon, 5 Feb 2018 14:39:28 +0100 Message-Id: <1517837972-1904-11-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 05 Feb 2018 13:42:30 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 da05d47..0753208 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -1044,12 +1044,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517839252949385.7372187860543; Mon, 5 Feb 2018 06:00:52 -0800 (PST) Received: from localhost ([::1]:45685 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihKF-0004aS-Tm for importer@patchew.org; Mon, 05 Feb 2018 09:00:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51631) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih38-0006zA-8L for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih2y-0007nB-Pe for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:10 -0500 Received: from mx1.redhat.com ([209.132.183.28]:53026) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih2o-0007c4-Ls; Mon, 05 Feb 2018 08:42:50 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C4428C04D2AC; Mon, 5 Feb 2018 13:42:49 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 929075C25E; Mon, 5 Feb 2018 13:42:30 +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: Mon, 5 Feb 2018 14:39:29 +0100 Message-Id: <1517837972-1904-12-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 05 Feb 2018 13:42:49 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 211a7bf..f0bd4d0 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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517838895399325.6063424402006; Mon, 5 Feb 2018 05:54:55 -0800 (PST) Received: from localhost ([::1]:45438 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihEU-0007y0-JE for importer@patchew.org; Mon, 05 Feb 2018 08:54:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51644) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih3A-00071t-NP for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih35-0007xn-8J for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:12 -0500 Received: from mx1.redhat.com ([209.132.183.28]:62120) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih30-0007p9-Ly; Mon, 05 Feb 2018 08:43:02 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D02CE7AE92; Mon, 5 Feb 2018 13:43:01 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 22B8F5F70E; Mon, 5 Feb 2018 13:42:49 +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: Mon, 5 Feb 2018 14:39:30 +0100 Message-Id: <1517837972-1904-13-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 05 Feb 2018 13:43:01 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 --- 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 b334c82..a760a68 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 @@ -1001,7 +1004,57 @@ static void create_pcie_irq_map(const VirtMachineSta= te *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; @@ -1114,6 +1167,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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 151783911805794.34655064180902; Mon, 5 Feb 2018 05:58:38 -0800 (PST) Received: from localhost ([::1]:45520 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihI0-0002ZU-Un for importer@patchew.org; Mon, 05 Feb 2018 08:58:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51719) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih3L-0007Ds-MO for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih3H-0008ML-8c for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:23 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59102) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih3A-00087q-0m; Mon, 05 Feb 2018 08:43:12 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2E4E71B3C5F; Mon, 5 Feb 2018 13:43:11 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 325195C25E; Mon, 5 Feb 2018 13:43:02 +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: Mon, 5 Feb 2018 14:39:31 +0100 Message-Id: <1517837972-1904-14-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 05 Feb 2018 13:43:11 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 Sat Apr 27 21:01:42 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; 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 1517839335758873.1171837153244; Mon, 5 Feb 2018 06:02:15 -0800 (PST) Received: from localhost ([::1]:45711 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eihLa-0005lK-VD for importer@patchew.org; Mon, 05 Feb 2018 09:02:15 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51786) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eih3Z-0007RG-4M for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eih3Y-0000SX-3y for qemu-devel@nongnu.org; Mon, 05 Feb 2018 08:43:37 -0500 Received: from mx1.redhat.com ([209.132.183.28]:53032) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eih3N-0000Ah-RY; Mon, 05 Feb 2018 08:43:26 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F06F978222; Mon, 5 Feb 2018 13:43:24 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-112.ams2.redhat.com [10.36.116.112]) by smtp.corp.redhat.com (Postfix) with ESMTP id 84B1B177C3; Mon, 5 Feb 2018 13:43: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: Mon, 5 Feb 2018 14:39:32 +0100 Message-Id: <1517837972-1904-15-git-send-email-eric.auger@redhat.com> In-Reply-To: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> References: <1517837972-1904-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 05 Feb 2018 13:43:25 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v8 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 a760a68..c88640f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1608,6 +1608,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) { @@ -1740,6 +1768,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; } @@ -1759,8 +1800,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