From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127479255154.17384045328333; Mon, 4 Jun 2018 08:51:19 -0700 (PDT) Received: from localhost ([::1]:40526 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrlO-0002A2-EV for importer@patchew.org; Mon, 04 Jun 2018 11:51:18 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41578) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQe-00027n-Ep for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQd-0002W0-46 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:52 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42578) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQa-0002TB-C6; Mon, 04 Jun 2018 11:29:48 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQU-00070p-Tz; Mon, 04 Jun 2018 16:29:42 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:29 +0100 Message-Id: <20180604152941.20374-2-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 01/13] iommu: Add IOMMU index concept to IOMMU API 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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" If an IOMMU supports mappings that care about the memory transaction attributes, then it no longer has a unique address -> output mapping, but more than one. We can represent these using an IOMMU index, analogous to TCG's mmu indexes. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Alex Benn=C3=A9e --- include/exec/memory.h | 55 +++++++++++++++++++++++++++++++++++++++++++ memory.c | 23 ++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h index eb2ba065195..fa6e98ee7be 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -206,6 +206,20 @@ enum IOMMUMemoryRegionAttr { * to report whenever mappings are changed, by calling * memory_region_notify_iommu() (or, if necessary, by calling * memory_region_notify_one() for each registered notifier). + * + * Conceptually an IOMMU provides a mapping from input address + * to an output TLB entry. If the IOMMU is aware of memory transaction + * attributes and the output TLB entry depends on the transaction + * attributes, we represent this using IOMMU indexes. Each index + * selects a particular translation table that the IOMMU has: + * @attrs_to_index returns the IOMMU index for a set of transaction attr= ibutes + * @translate takes an input address and an IOMMU index + * and the mapping returned can only depend on the input address and the + * IOMMU index. + * + * Most IOMMUs don't care about the transaction attributes and support + * only a single IOMMU index. A more complex IOMMU might have one index + * for secure transactions and one for non-secure transactions. */ typedef struct IOMMUMemoryRegionClass { /* private */ @@ -290,6 +304,29 @@ typedef struct IOMMUMemoryRegionClass { */ int (*get_attr)(IOMMUMemoryRegion *iommu, enum IOMMUMemoryRegionAttr a= ttr, void *data); + + /* Return the IOMMU index to use for a given set of transaction attrib= utes. + * + * Optional method: if an IOMMU only supports a single IOMMU index then + * the default implementation of memory_region_iommu_attrs_to_index() + * will return 0. + * + * The indexes supported by an IOMMU must be contiguous, starting at 0. + * + * @iommu: the IOMMUMemoryRegion + * @attrs: memory transaction attributes + */ + int (*attrs_to_index)(IOMMUMemoryRegion *iommu, MemTxAttrs attrs); + + /* Return the number of IOMMU indexes this IOMMU supports. + * + * Optional method: if this method is not provided, then + * memory_region_iommu_num_indexes() will return 1, indicating that + * only a single IOMMU index is supported. + * + * @iommu: the IOMMUMemoryRegion + */ + int (*num_indexes)(IOMMUMemoryRegion *iommu); } IOMMUMemoryRegionClass; =20 typedef struct CoalescedMemoryRange CoalescedMemoryRange; @@ -1054,6 +1091,24 @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *= iommu_mr, enum IOMMUMemoryRegionAttr attr, void *data); =20 +/** + * memory_region_iommu_attrs_to_index: return the IOMMU index to + * use for translations with the given memory transaction attributes. + * + * @iommu_mr: the memory region + * @attrs: the memory transaction attributes + */ +int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr, + MemTxAttrs attrs); + +/** + * memory_region_iommu_num_indexes: return the total number of IOMMU + * indexes that this IOMMU supports. + * + * @iommu_mr: the memory region + */ +int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr); + /** * memory_region_name: get a memory region's name * diff --git a/memory.c b/memory.c index 3212acc7f49..64f4a55d546 100644 --- a/memory.c +++ b/memory.c @@ -1915,6 +1915,29 @@ int memory_region_iommu_get_attr(IOMMUMemoryRegion *= iommu_mr, return imrc->get_attr(iommu_mr, attr, data); } =20 +int memory_region_iommu_attrs_to_index(IOMMUMemoryRegion *iommu_mr, + MemTxAttrs attrs) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_m= r); + + if (!imrc->attrs_to_index) { + return 0; + } + + return imrc->attrs_to_index(iommu_mr, attrs); +} + +int memory_region_iommu_num_indexes(IOMMUMemoryRegion *iommu_mr) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_GET_CLASS(iommu_m= r); + + if (!imrc->num_indexes) { + return 1; + } + + return imrc->num_indexes(iommu_mr); +} + void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) { uint8_t mask =3D 1 << client; --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127291244348.1187944162915; Mon, 4 Jun 2018 08:48:11 -0700 (PDT) Received: from localhost ([::1]:40505 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPriM-0008Gl-D4 for importer@patchew.org; Mon, 04 Jun 2018 11:48:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41670) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQh-0002Bf-Eb for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQf-0002Y7-Le for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:55 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42586) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQb-0002Tx-Sw; Mon, 04 Jun 2018 11:29:50 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQV-000712-OV; Mon, 04 Jun 2018 16:29:43 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:30 +0100 Message-Id: <20180604152941.20374-3-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 02/13] iommu: Add IOMMU index argument to notifier APIs 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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" Add support for multiple IOMMU indexes to the IOMMU notifier APIs. When initializing a notifier with iommu_notifier_init(), the caller must pass the IOMMU index that it is interested in. When a change happens, the IOMMU implementation must pass memory_region_notify_iommu() the IOMMU index that has changed and that notifiers must be called for. IOMMUs which support only a single index don't need to change. Callers which only really support working with IOMMUs with a single index can use the result of passing MEMTXATTRS_UNSPECIFIED to memory_region_iommu_attrs_to_index(). Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Alex Benn=C3=A9e --- include/exec/memory.h | 7 ++++++- hw/i386/intel_iommu.c | 6 +++--- hw/ppc/spapr_iommu.c | 2 +- hw/s390x/s390-pci-inst.c | 4 ++-- hw/vfio/common.c | 6 +++++- hw/virtio/vhost.c | 7 ++++++- memory.c | 8 +++++++- 7 files changed, 30 insertions(+), 10 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index fa6e98ee7be..ec75c45296e 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -98,18 +98,21 @@ struct IOMMUNotifier { /* Notify for address space range start <=3D addr <=3D end */ hwaddr start; hwaddr end; + int iommu_idx; QLIST_ENTRY(IOMMUNotifier) node; }; typedef struct IOMMUNotifier IOMMUNotifier; =20 static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn, IOMMUNotifierFlag flags, - hwaddr start, hwaddr end) + hwaddr start, hwaddr end, + int iommu_idx) { n->notify =3D fn; n->notifier_flags =3D flags; n->start =3D start; n->end =3D end; + n->iommu_idx =3D iommu_idx; } =20 /* @@ -1008,11 +1011,13 @@ uint64_t memory_region_iommu_get_min_page_size(IOMM= UMemoryRegion *iommu_mr); * should be notified with an UNMAP followed by a MAP. * * @iommu_mr: the memory region that was changed + * @iommu_idx: the IOMMU index for the translation table which has changed * @entry: the new entry in the IOMMU translation table. The entry * replaces all old entries for the same virtual I/O address range. * Deleted entries have .@perm =3D=3D 0. */ void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr, + int iommu_idx, IOMMUTLBEntry entry); =20 /** diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index b5a09b79089..9c0b45963b5 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -1023,7 +1023,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *= s, uint8_t bus_num, static int vtd_sync_shadow_page_hook(IOMMUTLBEntry *entry, void *private) { - memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry); + memory_region_notify_iommu((IOMMUMemoryRegion *)private, 0, *entry); return 0; } =20 @@ -1581,7 +1581,7 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOM= MUState *s, .addr_mask =3D size - 1, .perm =3D IOMMU_NONE, }; - memory_region_notify_iommu(&vtd_as->iommu, entry); + memory_region_notify_iommu(&vtd_as->iommu, 0, entry); } } } @@ -2015,7 +2015,7 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUS= tate *s, entry.iova =3D addr; entry.perm =3D IOMMU_NONE; entry.translated_addr =3D 0; - memory_region_notify_iommu(&vtd_dev_as->iommu, entry); + memory_region_notify_iommu(&vtd_dev_as->iommu, 0, entry); =20 done: return true; diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index aaa6010d5c9..301708e45eb 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -428,7 +428,7 @@ static target_ulong put_tce_emu(sPAPRTCETable *tcet, ta= rget_ulong ioba, entry.translated_addr =3D tce & page_mask; entry.addr_mask =3D ~page_mask; entry.perm =3D spapr_tce_iommu_access_flags(tce); - memory_region_notify_iommu(&tcet->iommu, entry); + memory_region_notify_iommu(&tcet->iommu, 0, entry); =20 return H_SUCCESS; } diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index d1a5f796783..7b61367ee31 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -589,7 +589,7 @@ static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, = S390IOTLBEntry *entry) } =20 notify.perm =3D IOMMU_NONE; - memory_region_notify_iommu(&iommu->iommu_mr, notify); + memory_region_notify_iommu(&iommu->iommu_mr, 0, notify); notify.perm =3D entry->perm; } =20 @@ -601,7 +601,7 @@ static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, = S390IOTLBEntry *entry) g_hash_table_replace(iommu->iotlb, &cache->iova, cache); } =20 - memory_region_notify_iommu(&iommu->iommu_mr, notify); + memory_region_notify_iommu(&iommu->iommu_mr, 0, notify); } =20 int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 8e57265edf1..fb396cf00ac 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -507,6 +507,7 @@ static void vfio_listener_region_add(MemoryListener *li= stener, if (memory_region_is_iommu(section->mr)) { VFIOGuestIOMMU *giommu; IOMMUMemoryRegion *iommu_mr =3D IOMMU_MEMORY_REGION(section->mr); + int iommu_idx; =20 trace_vfio_listener_region_add_iommu(iova, end); /* @@ -523,10 +524,13 @@ static void vfio_listener_region_add(MemoryListener *= listener, llend =3D int128_add(int128_make64(section->offset_within_region), section->size); llend =3D int128_sub(llend, int128_one()); + iommu_idx =3D memory_region_iommu_attrs_to_index(iommu_mr, + MEMTXATTRS_UNSPECIF= IED); iommu_notifier_init(&giommu->n, vfio_iommu_map_notify, IOMMU_NOTIFIER_ALL, section->offset_within_region, - int128_get64(llend)); + int128_get64(llend), + iommu_idx); QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next); =20 memory_region_register_iommu_notifier(section->mr, &giommu->n); diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 96175b214d7..b129cb9dddd 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -662,6 +662,8 @@ static void vhost_iommu_region_add(MemoryListener *list= ener, iommu_listener); struct vhost_iommu *iommu; Int128 end; + int iommu_idx; + IOMMUMemoryRegion *iommu_mr =3D IOMMU_MEMORY_REGION(section->mr); =20 if (!memory_region_is_iommu(section->mr)) { return; @@ -671,10 +673,13 @@ static void vhost_iommu_region_add(MemoryListener *li= stener, end =3D int128_add(int128_make64(section->offset_within_region), section->size); end =3D int128_sub(end, int128_one()); + iommu_idx =3D memory_region_iommu_attrs_to_index(iommu_mr, + MEMTXATTRS_UNSPECIFIED); iommu_notifier_init(&iommu->n, vhost_iommu_unmap_notify, IOMMU_NOTIFIER_UNMAP, section->offset_within_region, - int128_get64(end)); + int128_get64(end), + iommu_idx); iommu->mr =3D section->mr; iommu->iommu_offset =3D section->offset_within_address_space - section->offset_within_region; diff --git a/memory.c b/memory.c index 64f4a55d546..7aa75ff02d3 100644 --- a/memory.c +++ b/memory.c @@ -1799,6 +1799,9 @@ void memory_region_register_iommu_notifier(MemoryRegi= on *mr, iommu_mr =3D IOMMU_MEMORY_REGION(mr); assert(n->notifier_flags !=3D IOMMU_NOTIFIER_NONE); assert(n->start <=3D n->end); + assert(n->iommu_idx >=3D 0 && + n->iommu_idx < memory_region_iommu_num_indexes(iommu_mr)); + QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node); memory_region_update_iommu_notify_flags(iommu_mr); } @@ -1891,6 +1894,7 @@ void memory_region_notify_one(IOMMUNotifier *notifier, } =20 void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr, + int iommu_idx, IOMMUTLBEntry entry) { IOMMUNotifier *iommu_notifier; @@ -1898,7 +1902,9 @@ void memory_region_notify_iommu(IOMMUMemoryRegion *io= mmu_mr, assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr))); =20 IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) { - memory_region_notify_one(iommu_notifier, &entry); + if (iommu_notifier->iommu_idx =3D=3D iommu_idx) { + memory_region_notify_one(iommu_notifier, &entry); + } } } =20 --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127298967762.2900269563212; Mon, 4 Jun 2018 08:48:18 -0700 (PDT) Received: from localhost ([::1]:40506 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPriT-0008Ls-Pq for importer@patchew.org; Mon, 04 Jun 2018 11:48:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41550) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQd-00026j-Ff for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQb-0002Uz-Sh for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:51 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42560) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQY-0002SV-FL; Mon, 04 Jun 2018 11:29:46 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQW-00071Q-GX; Mon, 04 Jun 2018 16:29:44 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:31 +0100 Message-Id: <20180604152941.20374-4-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 03/13] iommu: Add IOMMU index argument to translate method 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Add an IOMMU index argument to the translate method of IOMMUs. Since all of our current IOMMU implementations support only a single IOMMU index, this has no effect on the behaviour. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Alex Benn=C3=A9e --- include/exec/memory.h | 3 ++- exec.c | 11 +++++++++-- hw/alpha/typhoon.c | 3 ++- hw/arm/smmuv3.c | 2 +- hw/dma/rc4030.c | 2 +- hw/i386/amd_iommu.c | 2 +- hw/i386/intel_iommu.c | 2 +- hw/ppc/spapr_iommu.c | 3 ++- hw/s390x/s390-pci-bus.c | 2 +- hw/sparc/sun4m_iommu.c | 3 ++- hw/sparc64/sun4u_iommu.c | 2 +- memory.c | 2 +- 12 files changed, 24 insertions(+), 13 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index ec75c45296e..050323f5323 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -251,9 +251,10 @@ typedef struct IOMMUMemoryRegionClass { * @iommu: the IOMMUMemoryRegion * @hwaddr: address to be translated within the memory region * @flag: requested access permissions + * @iommu_idx: IOMMU index for the translation */ IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag); + IOMMUAccessFlags flag, int iommu_idx); /* Returns minimum supported page size in bytes. * If this method is not provided then the minimum is assumed to * be TARGET_PAGE_SIZE. diff --git a/exec.c b/exec.c index f3fa4e9117f..033e74c36e4 100644 --- a/exec.c +++ b/exec.c @@ -498,8 +498,15 @@ static MemoryRegionSection address_space_translate_iom= mu(IOMMUMemoryRegion *iomm do { hwaddr addr =3D *xlat; IOMMUMemoryRegionClass *imrc =3D memory_region_get_iommu_class_noc= heck(iommu_mr); - IOMMUTLBEntry iotlb =3D imrc->translate(iommu_mr, addr, is_write ? - IOMMU_WO : IOMMU_RO); + int iommu_idx =3D 0; + IOMMUTLBEntry iotlb; + + if (imrc->attrs_to_index) { + iommu_idx =3D imrc->attrs_to_index(iommu_mr, attrs); + } + + iotlb =3D imrc->translate(iommu_mr, addr, is_write ? + IOMMU_WO : IOMMU_RO, iommu_idx); =20 if (!(iotlb.perm & (1 << is_write))) { goto unassigned; diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index 6a40869488e..d3ed7cdbe82 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -666,7 +666,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr= addr, Pchip and generate a machine check interrupt. */ static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, + int iommu_idx) { TyphoonPchip *pchip =3D container_of(iommu, TyphoonPchip, iommu); IOMMUTLBEntry ret; diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 42dc521c13a..978330900d5 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -538,7 +538,7 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, = SMMUTransCfg *cfg, } =20 static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, int iommu_idx) { SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); SMMUv3State *s =3D sdev->smmu; diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c index 5d4833eeca3..ccd8612888e 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -491,7 +491,7 @@ static const MemoryRegionOps jazzio_ops =3D { }; =20 static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr= addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, int iommu= _idx) { rc4030State *s =3D container_of(iommu, rc4030State, dma_mr); IOMMUTLBEntry ret =3D { diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c index 63d46ff6ee2..1fd669fef8a 100644 --- a/hw/i386/amd_iommu.c +++ b/hw/i386/amd_iommu.c @@ -991,7 +991,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr) } =20 static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, int iommu_idx) { AMDVIAddressSpace *as =3D container_of(iommu, AMDVIAddressSpace, iommu= ); AMDVIState *s =3D as->iommu_state; diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 9c0b45963b5..0a8cd4e9ccf 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -2471,7 +2471,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr, } =20 static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr = addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, int iommu_= idx) { VTDAddressSpace *vtd_as =3D container_of(iommu, VTDAddressSpace, iommu= ); IntelIOMMUState *s =3D vtd_as->iommu_state; diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 301708e45eb..1b0880ac9ed 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -112,7 +112,8 @@ static void spapr_tce_free_table(uint64_t *table, int f= d, uint32_t nb_table) /* Called from RCU critical section */ static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, + int iommu_idx) { sPAPRTCETable *tcet =3D container_of(iommu, sPAPRTCETable, iommu); uint64_t tce; diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 10da87458ee..e3e0ebb7f6c 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -484,7 +484,7 @@ uint16_t s390_guest_io_table_walk(uint64_t g_iota, hwad= dr addr, } =20 static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr ad= dr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, int iommu= _idx) { S390PCIIOMMU *iommu =3D container_of(mr, S390PCIIOMMU, iommu_mr); S390IOTLBEntry *entry; diff --git a/hw/sparc/sun4m_iommu.c b/hw/sparc/sun4m_iommu.c index b677601fc6b..7ca1e3fce41 100644 --- a/hw/sparc/sun4m_iommu.c +++ b/hw/sparc/sun4m_iommu.c @@ -282,7 +282,8 @@ static void iommu_bad_addr(IOMMUState *s, hwaddr addr, /* Called from RCU critical section */ static IOMMUTLBEntry sun4m_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flags) + IOMMUAccessFlags flags, + int iommu_idx) { IOMMUState *is =3D container_of(iommu, IOMMUState, iommu); hwaddr page, pa; diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c index eb3aaa87e64..1ef7645ba5f 100644 --- a/hw/sparc64/sun4u_iommu.c +++ b/hw/sparc64/sun4u_iommu.c @@ -73,7 +73,7 @@ /* Called from RCU critical section */ static IOMMUTLBEntry sun4u_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr, - IOMMUAccessFlags flag) + IOMMUAccessFlags flag, int iomm= u_idx) { IOMMUState *is =3D container_of(iommu, IOMMUState, iommu); hwaddr baseaddr, offset; diff --git a/memory.c b/memory.c index 7aa75ff02d3..21aa57d24cb 100644 --- a/memory.c +++ b/memory.c @@ -1832,7 +1832,7 @@ void memory_region_iommu_replay(IOMMUMemoryRegion *io= mmu_mr, IOMMUNotifier *n) granularity =3D memory_region_iommu_get_min_page_size(iommu_mr); =20 for (addr =3D 0; addr < memory_region_size(mr); addr +=3D granularity)= { - iotlb =3D imrc->translate(iommu_mr, addr, IOMMU_NONE); + iotlb =3D imrc->translate(iommu_mr, addr, IOMMU_NONE, n->iommu_idx= ); if (iotlb.perm !=3D IOMMU_NONE) { n->notify(n, &iotlb); } --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127127394448.8632262736015; Mon, 4 Jun 2018 08:45:27 -0700 (PDT) Received: from localhost ([::1]:40483 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrfd-0006MP-J4 for importer@patchew.org; Mon, 04 Jun 2018 11:45:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41598) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQe-00028X-Tm for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQd-0002WB-B5 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:52 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42560) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQZ-0002SV-H0; Mon, 04 Jun 2018 11:29:47 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQX-00071o-AR; Mon, 04 Jun 2018 16:29:45 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:32 +0100 Message-Id: <20180604152941.20374-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 04/13] exec.c: Handle IOMMUs in address_space_translate_for_iotlb() 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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" Currently we don't support board configurations that put an IOMMU in the path of the CPU's memory transactions, and instead just assert() if the memory region fonud in address_space_translate_for_iotlb() is an IOMMUMemoryRegion. Remove this limitation by having the function handle IOMMUs. This is mostly straightforward, but we must make sure we have a notifier registered for every IOMMU that a transaction has passed through, so that we can flush the TLB appropriately when any of the IOMMUs change their mappings. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- include/exec/exec-all.h | 3 +- include/qom/cpu.h | 3 + accel/tcg/cputlb.c | 3 +- exec.c | 135 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 140 insertions(+), 4 deletions(-) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 4d09eaba72d..e0ff19b7112 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -469,7 +469,8 @@ void tb_flush_jmp_cache(CPUState *cpu, target_ulong add= r); =20 MemoryRegionSection * address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, - hwaddr *xlat, hwaddr *plen); + hwaddr *xlat, hwaddr *plen, + MemTxAttrs attrs, int *prot); hwaddr memory_region_section_get_iotlb(CPUState *cpu, MemoryRegionSection *section, target_ulong vaddr, diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 9d3afc6c759..cce2fd6acc2 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -429,6 +429,9 @@ struct CPUState { uint16_t pending_tlb_flush; =20 int hvf_fd; + + /* track IOMMUs whose translations we've cached in the TCG TLB */ + GArray *iommu_notifiers; }; =20 QTAILQ_HEAD(CPUTailQ, CPUState); diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 05439039e91..c8acaf21e9f 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -632,7 +632,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulon= g vaddr, } =20 sz =3D size; - section =3D address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat= , &sz); + section =3D address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat= , &sz, + attrs, &prot); assert(sz >=3D TARGET_PAGE_SIZE); =20 tlb_debug("vaddr=3D" TARGET_FMT_lx " paddr=3D0x" TARGET_FMT_plx diff --git a/exec.c b/exec.c index 033e74c36e4..28181115cc2 100644 --- a/exec.c +++ b/exec.c @@ -650,18 +650,144 @@ MemoryRegion *flatview_translate(FlatView *fv, hwadd= r addr, hwaddr *xlat, return mr; } =20 +typedef struct TCGIOMMUNotifier { + IOMMUNotifier n; + MemoryRegion *mr; + CPUState *cpu; + int iommu_idx; + bool active; +} TCGIOMMUNotifier; + +static void tcg_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +{ + TCGIOMMUNotifier *notifier =3D container_of(n, TCGIOMMUNotifier, n); + + if (!notifier->active) { + return; + } + tlb_flush(notifier->cpu); + notifier->active =3D false; + /* We leave the notifier struct on the list to avoid reallocating it l= ater. + * Generally the number of IOMMUs a CPU deals with will be small. + * In any case we can't unregister the iommu notifier from a notify + * callback. + */ +} + +static void tcg_register_iommu_notifier(CPUState *cpu, + IOMMUMemoryRegion *iommu_mr, + int iommu_idx) +{ + /* Make sure this CPU has an IOMMU notifier registered for this + * IOMMU/IOMMU index combination, so that we can flush its TLB + * when the IOMMU tells us the mappings we've cached have changed. + */ + MemoryRegion *mr =3D MEMORY_REGION(iommu_mr); + TCGIOMMUNotifier *notifier; + int i; + + for (i =3D 0; i < cpu->iommu_notifiers->len; i++) { + notifier =3D &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier= , i); + if (notifier->mr =3D=3D mr && notifier->iommu_idx =3D=3D iommu_idx= ) { + break; + } + } + if (i =3D=3D cpu->iommu_notifiers->len) { + /* Not found, add a new entry at the end of the array */ + cpu->iommu_notifiers =3D g_array_set_size(cpu->iommu_notifiers, i = + 1); + notifier =3D &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier= , i); + + notifier->mr =3D mr; + notifier->iommu_idx =3D iommu_idx; + notifier->cpu =3D cpu; + /* Rather than trying to register interest in the specific part + * of the iommu's address space that we've accessed and then + * expand it later as subsequent accesses touch more of it, we + * just register interest in the whole thing, on the assumption + * that iommu reconfiguration will be rare. + */ + iommu_notifier_init(¬ifier->n, + tcg_iommu_unmap_notify, + IOMMU_NOTIFIER_UNMAP, + 0, + HWADDR_MAX, + iommu_idx); + memory_region_register_iommu_notifier(notifier->mr, ¬ifier->n); + } + + if (!notifier->active) { + notifier->active =3D true; + } +} + +static void tcg_iommu_free_notifier_list(CPUState *cpu) +{ + /* Destroy the CPU's notifier list */ + int i; + TCGIOMMUNotifier *notifier; + + for (i =3D 0; i < cpu->iommu_notifiers->len; i++) { + notifier =3D &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier= , i); + memory_region_unregister_iommu_notifier(notifier->mr, ¬ifier->n= ); + } + g_array_free(cpu->iommu_notifiers, true); +} + /* Called from RCU critical section */ MemoryRegionSection * address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr, - hwaddr *xlat, hwaddr *plen) + hwaddr *xlat, hwaddr *plen, + MemTxAttrs attrs, int *prot) { MemoryRegionSection *section; + IOMMUMemoryRegion *iommu_mr; + IOMMUMemoryRegionClass *imrc; + IOMMUTLBEntry iotlb; + int iommu_idx; AddressSpaceDispatch *d =3D atomic_rcu_read(&cpu->cpu_ases[asidx].memo= ry_dispatch); =20 - section =3D address_space_translate_internal(d, addr, xlat, plen, fals= e); + for (;;) { + section =3D address_space_translate_internal(d, addr, &addr, plen,= false); + + iommu_mr =3D memory_region_get_iommu(section->mr); + if (!iommu_mr) { + break; + } + + imrc =3D memory_region_get_iommu_class_nocheck(iommu_mr); + + iommu_idx =3D imrc->attrs_to_index(iommu_mr, attrs); + tcg_register_iommu_notifier(cpu, iommu_mr, iommu_idx); + /* We need all the permissions, so pass IOMMU_NONE so the IOMMU + * doesn't short-cut its translation table walk. + */ + iotlb =3D imrc->translate(iommu_mr, addr, IOMMU_NONE, iommu_idx); + addr =3D ((iotlb.translated_addr & ~iotlb.addr_mask) + | (addr & iotlb.addr_mask)); + /* Update the caller's prot bits to remove permissions the IOMMU + * is giving us a failure response for. If we get down to no + * permissions left at all we can give up now. + */ + if (!(iotlb.perm & IOMMU_RO)) { + *prot &=3D ~(PAGE_READ | PAGE_EXEC); + } + if (!(iotlb.perm & IOMMU_WO)) { + *prot &=3D ~PAGE_WRITE; + } + + if (!*prot) { + goto translate_fail; + } + + d =3D flatview_to_dispatch(address_space_to_flatview(iotlb.target_= as)); + } =20 assert(!memory_region_is_iommu(section->mr)); + *xlat =3D addr; return section; + +translate_fail: + return &d->map.sections[PHYS_SECTION_UNASSIGNED]; } #endif =20 @@ -820,6 +946,9 @@ void cpu_exec_unrealizefn(CPUState *cpu) if (qdev_get_vmsd(DEVICE(cpu)) =3D=3D NULL) { vmstate_unregister(NULL, &vmstate_cpu_common, cpu); } +#ifndef CONFIG_USER_ONLY + tcg_iommu_free_notifier_list(cpu); +#endif } =20 Property cpu_common_props[] =3D { @@ -867,6 +996,8 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp) if (cc->vmsd !=3D NULL) { vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); } + + cpu->iommu_notifiers =3D g_array_new(false, true, sizeof(TCGIOMMUNotif= ier)); #endif } =20 --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127044273841.0206381619566; Mon, 4 Jun 2018 08:44:04 -0700 (PDT) Received: from localhost ([::1]:40476 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPreN-0005Lx-3E for importer@patchew.org; Mon, 04 Jun 2018 11:44:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41691) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQi-0002CJ-2z for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQe-0002XP-S0 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:56 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42578) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQZ-0002TB-6l; Mon, 04 Jun 2018 11:29:47 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQY-00072c-3u; Mon, 04 Jun 2018 16:29:46 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:33 +0100 Message-Id: <20180604152941.20374-6-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 05/13] hw/misc/tz-mpc.c: Implement the Arm TrustZone Memory Protection Controller 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Implement the Arm TrustZone Memory Protection Controller, which sits in front of RAM and allows secure software to configure it to either pass through or reject transactions. We implement the MPC as a QEMU IOMMU, which will direct transactions either through to the devices and memory behind it or to a special "never works" AddressSpace if they are blocked. This initial commit implements the skeleton of the device: * it always permits accesses * it doesn't implement most of the registers * it doesn't implement the interrupt or other behaviour for blocked transactions Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Eric Auger --- hw/misc/Makefile.objs | 1 + include/hw/misc/tz-mpc.h | 70 ++++++ hw/misc/tz-mpc.c | 381 ++++++++++++++++++++++++++++++++ MAINTAINERS | 2 + default-configs/arm-softmmu.mak | 1 + hw/misc/trace-events | 7 + 6 files changed, 462 insertions(+) create mode 100644 include/hw/misc/tz-mpc.h create mode 100644 hw/misc/tz-mpc.c diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 00e834d0f06..7295e676a64 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -61,6 +61,7 @@ obj-$(CONFIG_MIPS_ITU) +=3D mips_itu.o obj-$(CONFIG_MPS2_FPGAIO) +=3D mps2-fpgaio.o obj-$(CONFIG_MPS2_SCC) +=3D mps2-scc.o =20 +obj-$(CONFIG_TZ_MPC) +=3D tz-mpc.o obj-$(CONFIG_TZ_PPC) +=3D tz-ppc.o obj-$(CONFIG_IOTKIT_SECCTL) +=3D iotkit-secctl.o =20 diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h new file mode 100644 index 00000000000..b5eaf1699ea --- /dev/null +++ b/include/hw/misc/tz-mpc.h @@ -0,0 +1,70 @@ +/* + * ARM TrustZone memory protection controller emulation + * + * Copyright (c) 2018 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +/* This is a model of the TrustZone memory protection controller (MPC). + * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM + * (DDI 0571G): + * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g + * + * The MPC sits in front of memory and allows secure software to + * configure it to either pass through or reject transactions. + * Rejected transactions may be configured to either be aborted, or to + * behave as RAZ/WI. An interrupt can be signalled for a rejected transact= ion. + * + * The MPC has a register interface which the guest uses to configure it. + * + * QEMU interface: + * + sysbus MMIO region 0: MemoryRegion for the MPC's config registers + * + sysbus MMIO region 1: MemoryRegion for the upstream end of the MPC + * + Property "downstream": MemoryRegion defining the downstream memory + * + Named GPIO output "irq": set for a transaction-failed interrupt + */ + +#ifndef TZ_MPC_H +#define TZ_MPC_H + +#include "hw/sysbus.h" + +#define TYPE_TZ_MPC "tz-mpc" +#define TZ_MPC(obj) OBJECT_CHECK(TZMPC, (obj), TYPE_TZ_MPC) + +#define TZ_NUM_PORTS 16 + +#define TYPE_TZ_MPC_IOMMU_MEMORY_REGION "tz-mpc-iommu-memory-region" + +typedef struct TZMPC TZMPC; + +struct TZMPC { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + + qemu_irq irq; + + /* Properties */ + MemoryRegion *downstream; + + hwaddr blocksize; + uint32_t blk_max; + + /* MemoryRegions exposed to user */ + MemoryRegion regmr; + IOMMUMemoryRegion upstream; + + /* MemoryRegion used internally */ + MemoryRegion blocked_io; + + AddressSpace downstream_as; + AddressSpace blocked_io_as; +}; + +#endif diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c new file mode 100644 index 00000000000..d4467ccc3b2 --- /dev/null +++ b/hw/misc/tz-mpc.c @@ -0,0 +1,381 @@ +/* + * ARM TrustZone memory protection controller emulation + * + * Copyright (c) 2018 Linaro Limited + * Written by Peter Maydell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 or + * (at your option) any later version. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/error.h" +#include "trace.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/tz-mpc.h" + +/* Our IOMMU has two IOMMU indexes, one for secure transactions and one for + * non-secure transactions. + */ +enum { + IOMMU_IDX_S, + IOMMU_IDX_NS, + IOMMU_NUM_INDEXES, +}; + +/* Config registers */ +REG32(CTRL, 0x00) +REG32(BLK_MAX, 0x10) +REG32(BLK_CFG, 0x14) +REG32(BLK_IDX, 0x18) +REG32(BLK_LUT, 0x1c) +REG32(INT_STAT, 0x20) +REG32(INT_CLEAR, 0x24) +REG32(INT_EN, 0x28) +REG32(INT_INFO1, 0x2c) +REG32(INT_INFO2, 0x30) +REG32(INT_SET, 0x34) +REG32(PIDR4, 0xfd0) +REG32(PIDR5, 0xfd4) +REG32(PIDR6, 0xfd8) +REG32(PIDR7, 0xfdc) +REG32(PIDR0, 0xfe0) +REG32(PIDR1, 0xfe4) +REG32(PIDR2, 0xfe8) +REG32(PIDR3, 0xfec) +REG32(CIDR0, 0xff0) +REG32(CIDR1, 0xff4) +REG32(CIDR2, 0xff8) +REG32(CIDR3, 0xffc) + +static const uint8_t tz_mpc_idregs[] =3D { + 0x04, 0x00, 0x00, 0x00, + 0x60, 0xb8, 0x1b, 0x00, + 0x0d, 0xf0, 0x05, 0xb1, +}; + +static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr, + uint64_t *pdata, + unsigned size, MemTxAttrs attrs) +{ + uint64_t r; + uint32_t offset =3D addr & ~0x3; + + switch (offset) { + case A_PIDR4: + case A_PIDR5: + case A_PIDR6: + case A_PIDR7: + case A_PIDR0: + case A_PIDR1: + case A_PIDR2: + case A_PIDR3: + case A_CIDR0: + case A_CIDR1: + case A_CIDR2: + case A_CIDR3: + r =3D tz_mpc_idregs[(offset - A_PIDR4) / 4]; + break; + case A_INT_CLEAR: + case A_INT_SET: + qemu_log_mask(LOG_GUEST_ERROR, + "TZ MPC register read: write-only offset 0x%x\n", + offset); + r =3D 0; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "TZ MPC register read: bad offset 0x%x\n", offset); + r =3D 0; + break; + } + + if (size !=3D 4) { + /* None of our registers are read-sensitive (except BLK_LUT, + * which can special case the "size not 4" case), so just + * pull the right bytes out of the word read result. + */ + r =3D extract32(r, (addr & 3) * 8, size * 8); + } + + trace_tz_mpc_reg_read(addr, r, size); + *pdata =3D r; + return MEMTX_OK; +} + +static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr, + uint64_t value, + unsigned size, MemTxAttrs attrs) +{ + uint32_t offset =3D addr & ~0x3; + + trace_tz_mpc_reg_write(addr, value, size); + + if (size !=3D 4) { + /* Expand the byte or halfword write to a full word size. + * In most cases we can do this with zeroes; the exceptions + * are CTRL, BLK_IDX and BLK_LUT. + */ + uint32_t oldval; + + switch (offset) { + /* As we add support for registers which need expansions + * other than zeroes we'll fill in cases here. + */ + default: + oldval =3D 0; + break; + } + value =3D deposit32(oldval, (addr & 3) * 8, size * 8, value); + } + + switch (offset) { + case A_PIDR4: + case A_PIDR5: + case A_PIDR6: + case A_PIDR7: + case A_PIDR0: + case A_PIDR1: + case A_PIDR2: + case A_PIDR3: + case A_CIDR0: + case A_CIDR1: + case A_CIDR2: + case A_CIDR3: + qemu_log_mask(LOG_GUEST_ERROR, + "TZ MPC register write: read-only offset 0x%x\n", of= fset); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "TZ MPC register write: bad offset 0x%x\n", offset); + break; + } + + return MEMTX_OK; +} + +static const MemoryRegionOps tz_mpc_reg_ops =3D { + .read_with_attrs =3D tz_mpc_reg_read, + .write_with_attrs =3D tz_mpc_reg_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 4, + .impl.min_access_size =3D 1, + .impl.max_access_size =3D 4, +}; + +/* Accesses only reach these read and write functions if the MPC is + * blocking them; non-blocked accesses go directly to the downstream + * memory region without passing through this code. + */ +static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr, + uint64_t *pdata, + unsigned size, MemTxAttrs attrs) +{ + trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure); + + *pdata =3D 0; + return MEMTX_OK; +} + +static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr, + uint64_t value, + unsigned size, MemTxAttrs attr= s) +{ + trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure); + + return MEMTX_OK; +} + +static const MemoryRegionOps tz_mpc_mem_blocked_ops =3D { + .read_with_attrs =3D tz_mpc_mem_blocked_read, + .write_with_attrs =3D tz_mpc_mem_blocked_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 8, + .impl.min_access_size =3D 1, + .impl.max_access_size =3D 8, +}; + +static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu, + hwaddr addr, IOMMUAccessFlags flags, + int iommu_idx) +{ + TZMPC *s =3D TZ_MPC(container_of(iommu, TZMPC, upstream)); + bool ok; + + IOMMUTLBEntry ret =3D { + .iova =3D addr & ~(s->blocksize - 1), + .translated_addr =3D addr & ~(s->blocksize - 1), + .addr_mask =3D s->blocksize - 1, + .perm =3D IOMMU_RW, + }; + + /* Look at the per-block configuration for this address, and + * return a TLB entry directing the transaction at either + * downstream_as or blocked_io_as, as appropriate. + * For the moment, always permit accesses. + */ + ok =3D true; + + trace_tz_mpc_translate(addr, flags, + iommu_idx =3D=3D IOMMU_IDX_S ? "S" : "NS", + ok ? "pass" : "block"); + + ret.target_as =3D ok ? &s->downstream_as : &s->blocked_io_as; + return ret; +} + +static int tz_mpc_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attr= s) +{ + /* We treat unspecified attributes like secure. Transactions with + * unspecified attributes come from places like + * cpu_physical_memory_write_rom() for initial image load, and we want + * those to pass through the from-reset "everything is secure" config. + * All the real during-emulation transactions from the CPU will + * specify attributes. + */ + return (attrs.unspecified || attrs.secure) ? IOMMU_IDX_S : IOMMU_IDX_N= S; +} + +static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu) +{ + return IOMMU_NUM_INDEXES; +} + +static void tz_mpc_reset(DeviceState *dev) +{ +} + +static void tz_mpc_init(Object *obj) +{ + DeviceState *dev =3D DEVICE(obj); + TZMPC *s =3D TZ_MPC(obj); + + qdev_init_gpio_out_named(dev, &s->irq, "irq", 1); +} + +static void tz_mpc_realize(DeviceState *dev, Error **errp) +{ + Object *obj =3D OBJECT(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + TZMPC *s =3D TZ_MPC(dev); + uint64_t size; + + /* We can't create the upstream end of the port until realize, + * as we don't know the size of the MR used as the downstream until th= en. + * We insist on having a downstream, to avoid complicating the code + * with handling the "don't know how big this is" case. It's easy + * enough for the user to create an unimplemented_device as downstream + * if they have nothing else to plug into this. + */ + if (!s->downstream) { + error_setg(errp, "MPC 'downstream' link not set"); + return; + } + + size =3D memory_region_size(s->downstream); + + memory_region_init_iommu(&s->upstream, sizeof(s->upstream), + TYPE_TZ_MPC_IOMMU_MEMORY_REGION, + obj, "tz-mpc-upstream", size); + + /* In real hardware the block size is configurable. In QEMU we could + * make it configurable but will need it to be at least as big as the + * target page size so we can execute out of the resulting MRs. Guest + * software is supposed to check the block size using the BLK_CFG + * register, so make it fixed at the page size. + */ + s->blocksize =3D memory_region_iommu_get_min_page_size(&s->upstream); + if (size % s->blocksize !=3D 0) { + error_setg(errp, + "MPC 'downstream' size %" PRId64 + " is not a multiple of %" HWADDR_PRIx " bytes", + size, s->blocksize); + object_unref(OBJECT(&s->upstream)); + return; + } + + /* BLK_MAX is the max value of BLK_IDX, which indexes an array of 32-b= it + * words, each bit of which indicates one block. + */ + s->blk_max =3D DIV_ROUND_UP(size / s->blocksize, 32); + + memory_region_init_io(&s->regmr, obj, &tz_mpc_reg_ops, + s, "tz-mpc-regs", 0x1000); + sysbus_init_mmio(sbd, &s->regmr); + + sysbus_init_mmio(sbd, MEMORY_REGION(&s->upstream)); + + /* This memory region is not exposed to users of this device as a + * sysbus MMIO region, but is instead used internally as something + * that our IOMMU translate function might direct accesses to. + */ + memory_region_init_io(&s->blocked_io, obj, &tz_mpc_mem_blocked_ops, + s, "tz-mpc-blocked-io", size); + + address_space_init(&s->downstream_as, s->downstream, + "tz-mpc-downstream"); + address_space_init(&s->blocked_io_as, &s->blocked_io, + "tz-mpc-blocked-io"); +} + +static const VMStateDescription tz_mpc_vmstate =3D { + .name =3D "tz-mpc", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_END_OF_LIST() + } +}; + +static Property tz_mpc_properties[] =3D { + DEFINE_PROP_LINK("downstream", TZMPC, downstream, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void tz_mpc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D tz_mpc_realize; + dc->vmsd =3D &tz_mpc_vmstate; + dc->reset =3D tz_mpc_reset; + dc->props =3D tz_mpc_properties; +} + +static const TypeInfo tz_mpc_info =3D { + .name =3D TYPE_TZ_MPC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(TZMPC), + .instance_init =3D tz_mpc_init, + .class_init =3D tz_mpc_class_init, +}; + +static void tz_mpc_iommu_memory_region_class_init(ObjectClass *klass, + void *data) +{ + IOMMUMemoryRegionClass *imrc =3D IOMMU_MEMORY_REGION_CLASS(klass); + + imrc->translate =3D tz_mpc_translate; + imrc->attrs_to_index =3D tz_mpc_attrs_to_index; + imrc->num_indexes =3D tz_mpc_num_indexes; +} + +static const TypeInfo tz_mpc_iommu_memory_region_info =3D { + .name =3D TYPE_TZ_MPC_IOMMU_MEMORY_REGION, + .parent =3D TYPE_IOMMU_MEMORY_REGION, + .class_init =3D tz_mpc_iommu_memory_region_class_init, +}; + +static void tz_mpc_register_types(void) +{ + type_register_static(&tz_mpc_info); + type_register_static(&tz_mpc_iommu_memory_region_info); +} + +type_init(tz_mpc_register_types); diff --git a/MAINTAINERS b/MAINTAINERS index 41cd3736a9b..9b712b92021 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -449,6 +449,8 @@ F: hw/char/cmsdk-apb-uart.c F: include/hw/char/cmsdk-apb-uart.h F: hw/misc/tz-ppc.c F: include/hw/misc/tz-ppc.h +F: hw/misc/tz-mpc.c +F: include/hw/misc/tz-mpc.h =20 ARM cores M: Peter Maydell diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.= mak index 8ba2558b36a..0f7dc2eb315 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -107,6 +107,7 @@ CONFIG_CMSDK_APB_UART=3Dy CONFIG_MPS2_FPGAIO=3Dy CONFIG_MPS2_SCC=3Dy =20 +CONFIG_TZ_MPC=3Dy CONFIG_TZ_PPC=3Dy CONFIG_IOTKIT=3Dy CONFIG_IOTKIT_SECCTL=3Dy diff --git a/hw/misc/trace-events b/hw/misc/trace-events index ec5a9f0da13..72bf9d57000 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -84,6 +84,13 @@ mos6522_set_sr_int(void) "set sr_int" mos6522_write(uint64_t addr, uint64_t val) "reg=3D0x%"PRIx64 " val=3D0x%"P= RIx64 mos6522_read(uint64_t addr, unsigned val) "reg=3D0x%"PRIx64 " val=3D0x%x" =20 +# hw/misc/tz-mpc.c +tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC reg= s read: offset 0x%x data 0x%" PRIx64 " size %u" +tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC re= gs write: offset 0x%x data 0x%" PRIx64 " size %u" +tz_mpc_mem_blocked_read(uint64_t addr, unsigned size, bool secure) "TZ MPC= blocked read: offset 0x%" PRIx64 " size %u secure %d" +tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool= secure) "TZ MPC blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 " siz= e %u secure %d" +tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *re= s) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s" + # hw/misc/tz-ppc.c tz_ppc_reset(void) "TZ PPC: reset" tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] =3D %d" --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528126745525754.6819897133763; Mon, 4 Jun 2018 08:39:05 -0700 (PDT) Received: from localhost ([::1]:40438 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrZT-0000s0-4B for importer@patchew.org; Mon, 04 Jun 2018 11:38:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41639) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQg-0002AJ-9m for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQe-0002XK-O7 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:54 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42578) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQb-0002TB-9s; Mon, 04 Jun 2018 11:29:49 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQZ-00072x-0f; Mon, 04 Jun 2018 16:29:47 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:34 +0100 Message-Id: <20180604152941.20374-7-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 06/13] hw/misc/tz-mpc.c: Implement registers 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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" Implement the missing registers for the TZ MPC. Signed-off-by: Peter Maydell --- include/hw/misc/tz-mpc.h | 10 +++ hw/misc/tz-mpc.c | 137 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 3 deletions(-) diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h index b5eaf1699ea..1fff4d6029a 100644 --- a/include/hw/misc/tz-mpc.h +++ b/include/hw/misc/tz-mpc.h @@ -48,6 +48,16 @@ struct TZMPC { =20 /*< public >*/ =20 + /* State */ + uint32_t ctrl; + uint32_t blk_idx; + uint32_t int_stat; + uint32_t int_en; + uint32_t int_info1; + uint32_t int_info2; + + uint32_t *blk_lut; + qemu_irq irq; =20 /* Properties */ diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c index d4467ccc3b2..9db55e23daf 100644 --- a/hw/misc/tz-mpc.c +++ b/hw/misc/tz-mpc.c @@ -28,16 +28,23 @@ enum { =20 /* Config registers */ REG32(CTRL, 0x00) + FIELD(CTRL, SEC_RESP, 4, 1) + FIELD(CTRL, AUTOINC, 8, 1) + FIELD(CTRL, LOCKDOWN, 31, 1) REG32(BLK_MAX, 0x10) REG32(BLK_CFG, 0x14) REG32(BLK_IDX, 0x18) REG32(BLK_LUT, 0x1c) REG32(INT_STAT, 0x20) + FIELD(INT_STAT, IRQ, 0, 1) REG32(INT_CLEAR, 0x24) + FIELD(INT_CLEAR, IRQ, 0, 1) REG32(INT_EN, 0x28) + FIELD(INT_EN, IRQ, 0, 1) REG32(INT_INFO1, 0x2c) REG32(INT_INFO2, 0x30) REG32(INT_SET, 0x34) + FIELD(INT_SET, IRQ, 0, 1) REG32(PIDR4, 0xfd0) REG32(PIDR5, 0xfd4) REG32(PIDR6, 0xfd8) @@ -57,14 +64,55 @@ static const uint8_t tz_mpc_idregs[] =3D { 0x0d, 0xf0, 0x05, 0xb1, }; =20 +static void tz_mpc_irq_update(TZMPC *s) +{ + qemu_set_irq(s->irq, s->int_stat && s->int_en); +} + static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr, uint64_t *pdata, unsigned size, MemTxAttrs attrs) { + TZMPC *s =3D TZ_MPC(opaque); uint64_t r; uint32_t offset =3D addr & ~0x3; =20 switch (offset) { + case A_CTRL: + r =3D s->ctrl; + break; + case A_BLK_MAX: + r =3D s->blk_max; + break; + case A_BLK_CFG: + /* We are never in "init in progress state", so this just indicates + * the block size. s->blocksize =3D=3D (1 << BLK_CFG + 5), so + * BLK_CFG =3D=3D ctz32(s->blocksize) - 5 + */ + r =3D ctz32(s->blocksize) - 5; + break; + case A_BLK_IDX: + r =3D s->blk_idx; + break; + case A_BLK_LUT: + r =3D s->blk_lut[s->blk_idx]; + if (size =3D=3D 4) { + s->blk_idx++; + s->blk_idx %=3D s->blk_max; + } + break; + case A_INT_STAT: + r =3D s->int_stat; + break; + case A_INT_EN: + r =3D s->int_en; + break; + case A_INT_INFO1: + r =3D s->int_info1; + break; + case A_INT_INFO2: + r =3D s->int_info2; + break; case A_PIDR4: case A_PIDR5: case A_PIDR6: @@ -110,6 +158,7 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwadd= r addr, uint64_t value, unsigned size, MemTxAttrs attrs) { + TZMPC *s =3D TZ_MPC(opaque); uint32_t offset =3D addr & ~0x3; =20 trace_tz_mpc_reg_write(addr, value, size); @@ -122,9 +171,15 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwad= dr addr, uint32_t oldval; =20 switch (offset) { - /* As we add support for registers which need expansions - * other than zeroes we'll fill in cases here. - */ + case A_CTRL: + oldval =3D s->ctrl; + break; + case A_BLK_IDX: + oldval =3D s->blk_idx; + break; + case A_BLK_LUT: + oldval =3D s->blk_lut[s->blk_idx]; + break; default: oldval =3D 0; break; @@ -132,7 +187,51 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwad= dr addr, value =3D deposit32(oldval, (addr & 3) * 8, size * 8, value); } =20 + if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) && + (offset =3D=3D A_CTRL || offset =3D=3D A_BLK_LUT || offset =3D=3D = A_INT_EN)) { + /* Lockdown mode makes these three registers read-only, and + * the only way out of it is to reset the device. + */ + qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x= %x " + "while MPC is in lockdown mode\n", offset); + return MEMTX_OK; + } + switch (offset) { + case A_CTRL: + /* We don't implement the 'data gating' feature so all other bits + * are reserved and we make them RAZ/WI. + */ + s->ctrl =3D value & (R_CTRL_SEC_RESP_MASK | + R_CTRL_AUTOINC_MASK | + R_CTRL_LOCKDOWN_MASK); + break; + case A_BLK_IDX: + s->blk_idx =3D value % s->blk_max; + break; + case A_BLK_LUT: + s->blk_lut[s->blk_idx] =3D value; + if (size =3D=3D 4) { + s->blk_idx++; + s->blk_idx %=3D s->blk_max; + } + break; + case A_INT_CLEAR: + if (value & R_INT_CLEAR_IRQ_MASK) { + s->int_stat =3D 0; + tz_mpc_irq_update(s); + } + break; + case A_INT_EN: + s->int_en =3D value & R_INT_EN_IRQ_MASK; + tz_mpc_irq_update(s); + break; + case A_INT_SET: + if (value & R_INT_SET_IRQ_MASK) { + s->int_stat =3D R_INT_STAT_IRQ_MASK; + tz_mpc_irq_update(s); + } + break; case A_PIDR4: case A_PIDR5: case A_PIDR6: @@ -248,6 +347,16 @@ static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu) =20 static void tz_mpc_reset(DeviceState *dev) { + TZMPC *s =3D TZ_MPC(dev); + + s->ctrl =3D 0x00000100; + s->blk_idx =3D 0; + s->int_stat =3D 0; + s->int_en =3D 1; + s->int_info1 =3D 0; + s->int_info2 =3D 0; + + memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t)); } =20 static void tz_mpc_init(Object *obj) @@ -321,13 +430,35 @@ static void tz_mpc_realize(DeviceState *dev, Error **= errp) "tz-mpc-downstream"); address_space_init(&s->blocked_io_as, &s->blocked_io, "tz-mpc-blocked-io"); + + s->blk_lut =3D g_new(uint32_t, s->blk_max); +} + +static int tz_mpc_post_load(void *opaque, int version_id) +{ + TZMPC *s =3D TZ_MPC(opaque); + + /* Check the incoming data doesn't point blk_idx off the end of blk_lu= t. */ + if (s->blk_idx >=3D s->blk_max) { + return -1; + } + return 0; } =20 static const VMStateDescription tz_mpc_vmstate =3D { .name =3D "tz-mpc", .version_id =3D 1, .minimum_version_id =3D 1, + .post_load =3D tz_mpc_post_load, .fields =3D (VMStateField[]) { + VMSTATE_UINT32(ctrl, TZMPC), + VMSTATE_UINT32(blk_idx, TZMPC), + VMSTATE_UINT32(int_stat, TZMPC), + VMSTATE_UINT32(int_en, TZMPC), + VMSTATE_UINT32(int_info1, TZMPC), + VMSTATE_UINT32(int_info2, TZMPC), + VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max, + 0, vmstate_info_uint32, uint32_t), VMSTATE_END_OF_LIST() } }; --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528126357512404.47869256338913; Mon, 4 Jun 2018 08:32:37 -0700 (PDT) Received: from localhost ([::1]:40402 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrTI-00046P-Ky for importer@patchew.org; Mon, 04 Jun 2018 11:32:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41582) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQe-00027y-Ju for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQd-0002WM-I6 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:52 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42586) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQa-0002Tx-UQ; Mon, 04 Jun 2018 11:29:49 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQZ-00073M-VT; Mon, 04 Jun 2018 16:29:47 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:35 +0100 Message-Id: <20180604152941.20374-8-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 07/13] hw/misc/tz-mpc.c: Implement correct blocked-access behaviour 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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 MPC is guest-configurable for whether blocked accesses: * should be RAZ/WI or cause a bus error * should generate an interrupt or not Implement this behaviour in the blocked-access handlers. Signed-off-by: Peter Maydell Reviewed-by: Eric Auger --- hw/misc/tz-mpc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c index 9db55e23daf..704bb3fb44d 100644 --- a/hw/misc/tz-mpc.c +++ b/hw/misc/tz-mpc.c @@ -43,6 +43,9 @@ REG32(INT_EN, 0x28) FIELD(INT_EN, IRQ, 0, 1) REG32(INT_INFO1, 0x2c) REG32(INT_INFO2, 0x30) + FIELD(INT_INFO2, HMASTER, 0, 16) + FIELD(INT_INFO2, HNONSEC, 16, 1) + FIELD(INT_INFO2, CFG_NS, 17, 1) REG32(INT_SET, 0x34) FIELD(INT_SET, IRQ, 0, 1) REG32(PIDR4, 0xfd0) @@ -266,6 +269,45 @@ static const MemoryRegionOps tz_mpc_reg_ops =3D { .impl.max_access_size =3D 4, }; =20 +static inline bool tz_mpc_cfg_ns(TZMPC *s, hwaddr addr) +{ + /* Return the cfg_ns bit from the LUT for the specified address */ + hwaddr blknum =3D addr / s->blocksize; + hwaddr blkword =3D blknum / 32; + uint32_t blkbit =3D 1U << (blknum % 32); + + /* This would imply the address was larger than the size we + * defined this memory region to be, so it can't happen. + */ + assert(blkword < s->blk_max); + return s->blk_lut[blkword] & blkbit; +} + +static MemTxResult tz_mpc_handle_block(TZMPC *s, hwaddr addr, MemTxAttrs a= ttrs) +{ + /* Handle a blocked transaction: raise IRQ, capture info, etc */ + if (!s->int_stat) { + /* First blocked transfer: capture information into INT_INFO1 and + * INT_INFO2. Subsequent transfers are still blocked but don't + * capture information until the guest clears the interrupt. + */ + + s->int_info1 =3D addr; + s->int_info2 =3D 0; + s->int_info2 =3D FIELD_DP32(s->int_info2, INT_INFO2, HMASTER, + attrs.requester_id & 0xffff); + s->int_info2 =3D FIELD_DP32(s->int_info2, INT_INFO2, HNONSEC, + ~attrs.secure); + s->int_info2 =3D FIELD_DP32(s->int_info2, INT_INFO2, CFG_NS, + tz_mpc_cfg_ns(s, addr)); + s->int_stat |=3D R_INT_STAT_IRQ_MASK; + tz_mpc_irq_update(s); + } + + /* Generate bus error if desired; otherwise RAZ/WI */ + return (s->ctrl & R_CTRL_SEC_RESP_MASK) ? MEMTX_ERROR : MEMTX_OK; +} + /* Accesses only reach these read and write functions if the MPC is * blocking them; non-blocked accesses go directly to the downstream * memory region without passing through this code. @@ -274,19 +316,23 @@ static MemTxResult tz_mpc_mem_blocked_read(void *opaq= ue, hwaddr addr, uint64_t *pdata, unsigned size, MemTxAttrs attrs) { + TZMPC *s =3D TZ_MPC(opaque); + trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure); =20 *pdata =3D 0; - return MEMTX_OK; + return tz_mpc_handle_block(s, addr, attrs); } =20 static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr, uint64_t value, unsigned size, MemTxAttrs attr= s) { + TZMPC *s =3D TZ_MPC(opaque); + trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure); =20 - return MEMTX_OK; + return tz_mpc_handle_block(s, addr, attrs); } =20 static const MemoryRegionOps tz_mpc_mem_blocked_ops =3D { --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528126548875982.1560270309442; Mon, 4 Jun 2018 08:35:48 -0700 (PDT) Received: from localhost ([::1]:40417 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrWN-0006TW-Oz for importer@patchew.org; Mon, 04 Jun 2018 11:35:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41655) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQg-0002B3-QB for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQf-0002Y0-F5 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:54 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42578) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQc-0002TB-9l; Mon, 04 Jun 2018 11:29:50 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQa-00073u-Pq; Mon, 04 Jun 2018 16:29:48 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:36 +0100 Message-Id: <20180604152941.20374-9-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 08/13] hw/misc/tz_mpc.c: Honour the BLK_LUT settings in translate 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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 final part of the Memory Protection Controller we need to implement is actually using the BLK_LUT data programmed by the guest to determine whether to block the transaction or not. Since this means we now change transaction mappings when the guest writes to BLK_LUT, we must also call the IOMMU notifiers at that point. Signed-off-by: Peter Maydell --- hw/misc/tz-mpc.c | 50 ++++++++++++++++++++++++++++++++++++++++++-- hw/misc/trace-events | 1 + 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c index 704bb3fb44d..7a6117c90b3 100644 --- a/hw/misc/tz-mpc.c +++ b/hw/misc/tz-mpc.c @@ -72,6 +72,50 @@ static void tz_mpc_irq_update(TZMPC *s) qemu_set_irq(s->irq, s->int_stat && s->int_en); } =20 +static void tz_mpc_iommu_notify(TZMPC *s, uint32_t lutidx, + uint32_t oldlut, uint32_t newlut) +{ + /* Called when the LUT word at lutidx has changed from oldlut to newlu= t; + * must call the IOMMU notifiers for the changed blocks. + */ + IOMMUTLBEntry entry =3D { + .addr_mask =3D s->blocksize - 1, + }; + hwaddr addr =3D lutidx * s->blocksize * 32; + int i; + + for (i =3D 0; i < 32; i++, addr +=3D s->blocksize) { + if (!((oldlut ^ newlut) & (1 << i))) { + continue; + } + /* This changes the mappings for both the S and the NS space, + * so we need to do four notifies: an UNMAP then a MAP for each. + */ + + trace_tz_mpc_iommu_notify(addr); + entry.iova =3D addr; + entry.translated_addr =3D addr; + + entry.perm =3D IOMMU_NONE; + memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry); + memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry); + + entry.perm =3D IOMMU_RW; + if (newlut & (1 << i)) { + entry.target_as =3D &s->blocked_io_as; + } else { + entry.target_as =3D &s->downstream_as; + } + memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry); + if (newlut & (1 << i)) { + entry.target_as =3D &s->downstream_as; + } else { + entry.target_as =3D &s->blocked_io_as; + } + memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry); + } +} + static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr, uint64_t *pdata, unsigned size, MemTxAttrs attrs) @@ -213,6 +257,7 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwadd= r addr, s->blk_idx =3D value % s->blk_max; break; case A_BLK_LUT: + tz_mpc_iommu_notify(s, s->blk_idx, s->blk_lut[s->blk_idx], value); s->blk_lut[s->blk_idx] =3D value; if (size =3D=3D 4) { s->blk_idx++; @@ -362,9 +407,10 @@ static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegio= n *iommu, /* Look at the per-block configuration for this address, and * return a TLB entry directing the transaction at either * downstream_as or blocked_io_as, as appropriate. - * For the moment, always permit accesses. + * If the LUT cfg_ns bit is 1, only non-secure transactions + * may pass. If the bit is 0, only secure transactions may pass. */ - ok =3D true; + ok =3D tz_mpc_cfg_ns(s, addr) =3D=3D (iommu_idx =3D=3D IOMMU_IDX_NS); =20 trace_tz_mpc_translate(addr, flags, iommu_idx =3D=3D IOMMU_IDX_S ? "S" : "NS", diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 72bf9d57000..c956e1419b7 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -90,6 +90,7 @@ tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned= size) "TZ MPC regs wri tz_mpc_mem_blocked_read(uint64_t addr, unsigned size, bool secure) "TZ MPC= blocked read: offset 0x%" PRIx64 " size %u secure %d" tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool= secure) "TZ MPC blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 " siz= e %u secure %d" tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *re= s) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s" +tz_mpc_iommu_notify(uint64_t addr) "TZ MPC iommu: notifying UNMAP/MAP for = 0x%" PRIx64 =20 # hw/misc/tz-ppc.c tz_ppc_reset(void) "TZ PPC: reset" --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528126810628685.4467368053294; Mon, 4 Jun 2018 08:40:10 -0700 (PDT) Received: from localhost ([::1]:40441 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrab-00026O-OQ for importer@patchew.org; Mon, 04 Jun 2018 11:40:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41651) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQg-0002Aw-Na for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQf-0002Xv-Dz for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:54 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42596) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQc-0002V4-Hz; Mon, 04 Jun 2018 11:29:50 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQb-00074j-Ji; Mon, 04 Jun 2018 16:29:49 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:37 +0100 Message-Id: <20180604152941.20374-10-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 09/13] hw/core/or-irq: Support more than 16 inputs to an OR gate 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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" For the IoTKit MPC support, we need to wire together the interrupt outputs of 17 MPCs; this exceeds the current value of MAX_OR_LINES. Increase MAX_OR_LINES to 32 (which should be enough for anyone). The tricky part is retaining the migration compatibility for existing OR gates; we add a subsection which is only used for larger OR gates, and define it such that we can freely increase MAX_OR_LINES in future (or even move to a dynamically allocated levels[] array without an upper size limit) without breaking compatibility. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- include/hw/or-irq.h | 5 ++++- hw/core/or-irq.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/include/hw/or-irq.h b/include/hw/or-irq.h index 3f6fc1b58a4..5a31e5a1881 100644 --- a/include/hw/or-irq.h +++ b/include/hw/or-irq.h @@ -31,7 +31,10 @@ =20 #define TYPE_OR_IRQ "or-irq" =20 -#define MAX_OR_LINES 16 +/* This can safely be increased if necessary without breaking + * migration compatibility (as long as it remains greater than 15). + */ +#define MAX_OR_LINES 32 =20 typedef struct OrIRQState qemu_or_irq; =20 diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c index f9d76c46415..a86901b673c 100644 --- a/hw/core/or-irq.c +++ b/hw/core/or-irq.c @@ -66,14 +66,49 @@ static void or_irq_init(Object *obj) qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1); } =20 +/* The original version of this device had a fixed 16 entries in its + * VMState array; devices with more inputs than this need to + * migrate the extra lines via a subsection. + * The subsection migrates as much of the levels[] array as is needed + * (including repeating the first 16 elements), to avoid the awkwardness + * of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT1= 6. + */ +#define OLD_MAX_OR_LINES 16 +#if MAX_OR_LINES < OLD_MAX_OR_LINES +#error MAX_OR_LINES must be at least 16 for migration compatibility +#endif + +static bool vmstate_extras_needed(void *opaque) +{ + qemu_or_irq *s =3D OR_IRQ(opaque); + + return s->num_lines >=3D OLD_MAX_OR_LINES; +} + +static const VMStateDescription vmstate_or_irq_extras =3D { + .name =3D "or-irq-extras", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D vmstate_extras_needed, + .fields =3D (VMStateField[]) { + VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0, + vmstate_info_bool, bool), + VMSTATE_END_OF_LIST(), + }, +}; + static const VMStateDescription vmstate_or_irq =3D { .name =3D TYPE_OR_IRQ, .version_id =3D 1, .minimum_version_id =3D 1, .fields =3D (VMStateField[]) { - VMSTATE_BOOL_ARRAY(levels, qemu_or_irq, MAX_OR_LINES), + VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES), VMSTATE_END_OF_LIST(), - } + }, + .subsections =3D (const VMStateDescription*[]) { + &vmstate_or_irq_extras, + NULL + }, }; =20 static Property or_irq_properties[] =3D { --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127640337615.0714545521809; Mon, 4 Jun 2018 08:54:00 -0700 (PDT) Received: from localhost ([::1]:40538 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrnz-0004WO-Hi for importer@patchew.org; Mon, 04 Jun 2018 11:53:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41727) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQj-0002Eq-NR for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQi-0002aT-H8 for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:57 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42602) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQf-0002WR-2R; Mon, 04 Jun 2018 11:29:53 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQc-000756-DB; Mon, 04 Jun 2018 16:29:50 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:38 +0100 Message-Id: <20180604152941.20374-11-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 10/13] hw/misc/iotkit-secctl.c: Implement SECMPCINTSTATUS 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson 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" Implement the SECMPCINTSTATUS register. This is the only register in the security controller that deals with Memory Protection Controllers, and it simply provides a read-only view of the interrupt lines from the various MPCs in the system. Signed-off-by: Peter Maydell --- include/hw/misc/iotkit-secctl.h | 8 +++++++ hw/misc/iotkit-secctl.c | 38 +++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secct= l.h index faad0c91901..082c14c925e 100644 --- a/include/hw/misc/iotkit-secctl.h +++ b/include/hw/misc/iotkit-secctl.h @@ -39,6 +39,11 @@ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status + * Controlling the MPC in the IoTKit: + * + named GPIO input mpc_status + * Controlling each of the 16 expansion MPCs which a system using the IoTK= it + * might provide: + * + named GPIO inputs mpcexp_status[0..15] */ =20 #ifndef IOTKIT_SECCTL_H @@ -55,6 +60,8 @@ #define IOTS_NUM_APB_PPC 2 #define IOTS_NUM_APB_EXP_PPC 4 #define IOTS_NUM_AHB_EXP_PPC 4 +#define IOTS_NUM_EXP_MPC 16 +#define IOTS_NUM_MPC 1 =20 typedef struct IoTKitSecCtl IoTKitSecCtl; =20 @@ -94,6 +101,7 @@ struct IoTKitSecCtl { uint32_t secrespcfg; uint32_t nsccfg; uint32_t brginten; + uint32_t mpcintstatus; =20 IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC]; IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC]; diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c index ddd1584d341..de4fd8e36d2 100644 --- a/hw/misc/iotkit-secctl.c +++ b/hw/misc/iotkit-secctl.c @@ -139,6 +139,9 @@ static MemTxResult iotkit_secctl_s_read(void *opaque, h= waddr addr, case A_NSCCFG: r =3D s->nsccfg; break; + case A_SECMPCINTSTATUS: + r =3D s->mpcintstatus; + break; case A_SECPPCINTSTAT: r =3D s->secppcintstat; break; @@ -186,7 +189,6 @@ static MemTxResult iotkit_secctl_s_read(void *opaque, h= waddr addr, case A_APBSPPPCEXP3: r =3D s->apbexp[offset_to_ppc_idx(offset)].sp; break; - case A_SECMPCINTSTATUS: case A_SECMSCINTSTAT: case A_SECMSCINTEN: case A_NSMSCEXP: @@ -572,6 +574,20 @@ static void iotkit_secctl_reset(DeviceState *dev) foreach_ppc(s, iotkit_secctl_reset_ppc); } =20 +static void iotkit_secctl_mpc_status(void *opaque, int n, int level) +{ + IoTKitSecCtl *s =3D IOTKIT_SECCTL(opaque); + + s->mpcintstatus =3D deposit32(s->mpcintstatus, 0, 1, !!level); +} + +static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level) +{ + IoTKitSecCtl *s =3D IOTKIT_SECCTL(opaque); + + s->mpcintstatus =3D deposit32(s->mpcintstatus, n + 16, 1, !!level); +} + static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level) { IoTKitSecCtlPPC *ppc =3D opaque; @@ -640,6 +656,10 @@ static void iotkit_secctl_init(Object *obj) qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1); qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1); =20 + qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1= ); + qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status, + "mpcexp_status", IOTS_NUM_EXP_MPC); + memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops, s, "iotkit-secctl-s-regs", 0x1000); memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops, @@ -660,6 +680,16 @@ static const VMStateDescription iotkit_secctl_ppc_vmst= ate =3D { } }; =20 +static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate =3D { + .name =3D "iotkit-secctl-mpcintstatus", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription iotkit_secctl_vmstate =3D { .name =3D "iotkit-secctl", .version_id =3D 1, @@ -677,7 +707,11 @@ static const VMStateDescription iotkit_secctl_vmstate = =3D { VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1, iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC), VMSTATE_END_OF_LIST() - } + }, + .subsections =3D (const VMStateDescription*[]) { + &iotkit_secctl_mpcintstatus_vmstate, + NULL + }, }; =20 static void iotkit_secctl_class_init(ObjectClass *klass, void *data) --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127467591840.9939810905626; Mon, 4 Jun 2018 08:51:07 -0700 (PDT) Received: from localhost ([::1]:40525 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrlC-00022v-H1 for importer@patchew.org; Mon, 04 Jun 2018 11:51:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41706) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQi-0002D8-Ij for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQh-0002ZQ-8f for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:56 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42602) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQe-0002WR-5m; Mon, 04 Jun 2018 11:29:52 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQd-000764-6b; Mon, 04 Jun 2018 16:29:51 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:39 +0100 Message-Id: <20180604152941.20374-12-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 11/13] hw/arm/iotkit: Instantiate MPC 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Wire up the one MPC that is part of the IoTKit itself. For the moment we don't wire up its interrupt line. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- include/hw/arm/iotkit.h | 2 ++ hw/arm/iotkit.c | 38 +++++++++++++++++++++++++++----------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h index c6129d926b6..b21cf1ab9d1 100644 --- a/include/hw/arm/iotkit.h +++ b/include/hw/arm/iotkit.h @@ -51,6 +51,7 @@ #include "hw/arm/armv7m.h" #include "hw/misc/iotkit-secctl.h" #include "hw/misc/tz-ppc.h" +#include "hw/misc/tz-mpc.h" #include "hw/timer/cmsdk-apb-timer.h" #include "hw/misc/unimp.h" #include "hw/or-irq.h" @@ -74,6 +75,7 @@ typedef struct IoTKit { IoTKitSecCtl secctl; TZPPC apb_ppc0; TZPPC apb_ppc1; + TZMPC mpc; CMSDKAPBTIMER timer0; CMSDKAPBTIMER timer1; qemu_or_irq ppc_irq_orgate; diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c index 234185e8f78..160e40c7449 100644 --- a/hw/arm/iotkit.c +++ b/hw/arm/iotkit.c @@ -130,6 +130,7 @@ static void iotkit_init(Object *obj) TYPE_TZ_PPC); init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1), TYPE_TZ_PPC); + init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC); init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0), TYPE_CMSDK_APB_TIMER); init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1), @@ -266,15 +267,6 @@ static void iotkit_realize(DeviceState *dev, Error **e= rrp) */ make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x4000000= 0); =20 - /* This RAM should be behind a Memory Protection Controller, but we - * don't implement that yet. - */ - memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &e= rr); - if (err) { - error_propagate(errp, err); - return; - } - memory_region_add_subregion(&s->container, 0x20000000, &s->sram0); =20 /* Security controller */ object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err); @@ -310,6 +302,32 @@ static void iotkit_realize(DeviceState *dev, Error **e= rrp) qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0, qdev_get_gpio_in(dev_splitter, 0)); =20 + /* This RAM lives behind the Memory Protection Controller */ + memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &e= rr); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0), + "downstream", &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + /* Map the upstream end of the MPC into the right place... */ + memory_region_add_subregion(&s->container, 0x20000000, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->= mpc), + 1)); + /* ...and its register interface */ + memory_region_add_subregion(&s->container, 0x50083000, + sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->= mpc), + 0)); + /* Devices behind APB PPC0: * 0x40000000: timer0 * 0x40001000: timer1 @@ -473,8 +491,6 @@ static void iotkit_realize(DeviceState *dev, Error **er= rp) create_unimplemented_device("NS watchdog", 0x40081000, 0x1000); create_unimplemented_device("S watchdog", 0x50081000, 0x1000); =20 - create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000); - for (i =3D 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { Object *splitter =3D OBJECT(&s->ppc_irq_splitter[i]); =20 --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528128990415346.88619027764923; Mon, 4 Jun 2018 09:16:30 -0700 (PDT) Received: from localhost ([::1]:40795 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPs9l-0006Ck-AB for importer@patchew.org; Mon, 04 Jun 2018 12:16:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49818) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrqA-0007E0-9b for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:56:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrq9-0007xE-2Q for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:56:14 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42658) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrq6-0007uW-AX; Mon, 04 Jun 2018 11:56:10 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQd-00076L-Tj; Mon, 04 Jun 2018 16:29:51 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:40 +0100 Message-Id: <20180604152941.20374-13-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 12/13] hw/arm/iotkit: Wire up MPC interrupt lines 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 The interrupt outputs from the MPC in the IoTKit and the expansion MPCs in the board must be wired up to the security controller, and also all ORed together to produce a single line to the NVIC. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- include/hw/arm/iotkit.h | 6 ++++ hw/arm/iotkit.c | 74 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h index b21cf1ab9d1..2cddde55dd1 100644 --- a/include/hw/arm/iotkit.h +++ b/include/hw/arm/iotkit.h @@ -42,6 +42,9 @@ * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable * + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear * + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status + * Controlling each of the 16 expansion MPCs which a system using the IoTK= it + * might provide: + * + named GPIO inputs mpcexp_status[0..15] */ =20 #ifndef IOTKIT_H @@ -81,6 +84,8 @@ typedef struct IoTKit { qemu_or_irq ppc_irq_orgate; SplitIRQ sec_resp_splitter; SplitIRQ ppc_irq_splitter[NUM_PPCS]; + SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC]; + qemu_or_irq mpc_irq_orgate; =20 UnimplementedDeviceState dualtimer; UnimplementedDeviceState s32ktimer; @@ -99,6 +104,7 @@ typedef struct IoTKit { qemu_irq nsc_cfg_in; =20 qemu_irq irq_status_in[NUM_EXTERNAL_PPCS]; + qemu_irq mpcexp_status_in[IOTS_NUM_EXP_MPC]; =20 uint32_t nsccfg; =20 diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c index 160e40c7449..133d5bb34f4 100644 --- a/hw/arm/iotkit.c +++ b/hw/arm/iotkit.c @@ -131,6 +131,18 @@ static void iotkit_init(Object *obj) init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1), TYPE_TZ_PPC); init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC); + object_initialize(&s->mpc_irq_orgate, sizeof(s->mpc_irq_orgate), + TYPE_OR_IRQ); + object_property_add_child(obj, "mpc-irq-orgate", + OBJECT(&s->mpc_irq_orgate), &error_abort); + for (i =3D 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) { + char *name =3D g_strdup_printf("mpc-irq-splitter-%d", i); + SplitIRQ *splitter =3D &s->mpc_irq_splitter[i]; + + object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ); + object_property_add_child(obj, name, OBJECT(splitter), &error_abor= t); + g_free(name); + } init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0), TYPE_CMSDK_APB_TIMER); init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1), @@ -163,6 +175,12 @@ static void iotkit_exp_irq(void *opaque, int n, int le= vel) qemu_set_irq(s->exp_irqs[n], level); } =20 +static void iotkit_mpcexp_status(void *opaque, int n, int level) +{ + IoTKit *s =3D IOTKIT(opaque); + qemu_set_irq(s->mpcexp_status_in[n], level); +} + static void iotkit_realize(DeviceState *dev, Error **errp) { IoTKit *s =3D IOTKIT(dev); @@ -328,6 +346,22 @@ static void iotkit_realize(DeviceState *dev, Error **e= rrp) sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->= mpc), 0)); =20 + /* We must OR together lines from the MPC splitters to go to the NVIC = */ + object_property_set_int(OBJECT(&s->mpc_irq_orgate), + IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", = &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true, + "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), 9)); + /* Devices behind APB PPC0: * 0x40000000: timer0 * 0x40001000: timer1 @@ -536,6 +570,46 @@ static void iotkit_realize(DeviceState *dev, Error **e= rrp) g_free(gpioname); } =20 + /* Wire up the splitters for the MPC IRQs */ + for (i =3D 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) { + SplitIRQ *splitter =3D &s->mpc_irq_splitter[i]; + DeviceState *dev_splitter =3D DEVICE(splitter); + + object_property_set_int(OBJECT(splitter), 2, "num-lines", &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_bool(OBJECT(splitter), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + if (i < IOTS_NUM_EXP_MPC) { + /* Splitter input is from GPIO input line */ + s->mpcexp_status_in[i] =3D qdev_get_gpio_in(dev_splitter, 0); + qdev_connect_gpio_out(dev_splitter, 0, + qdev_get_gpio_in_named(dev_secctl, + "mpcexp_status", = i)); + } else { + /* Splitter input is from our own MPC */ + qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0, + qdev_get_gpio_in(dev_splitter, 0)); + qdev_connect_gpio_out(dev_splitter, 0, + qdev_get_gpio_in_named(dev_secctl, + "mpc_status", 0)); + } + + qdev_connect_gpio_out(dev_splitter, 1, + qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate),= i)); + } + /* Create GPIO inputs which will pass the line state for our + * mpcexp_irq inputs to the correct splitter devices. + */ + qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status", + IOTS_NUM_EXP_MPC); + iotkit_forward_sec_resp_cfg(s); =20 system_clock_scale =3D NANOSECONDS_PER_SECOND / s->mainclk_frq; --=20 2.17.1 From nobody Sat Apr 27 19:26:16 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=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1528127665127142.76920036086278; Mon, 4 Jun 2018 08:54:25 -0700 (PDT) Received: from localhost ([::1]:40540 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fProO-0004ta-7b for importer@patchew.org; Mon, 04 Jun 2018 11:54:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41735) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fPrQk-0002FK-6N for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fPrQj-0002ax-2T for qemu-devel@nongnu.org; Mon, 04 Jun 2018 11:29:58 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42612) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fPrQf-0002Xf-Nn; Mon, 04 Jun 2018 11:29:53 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fPrQe-00076r-OQ; Mon, 04 Jun 2018 16:29:52 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Mon, 4 Jun 2018 16:29:41 +0100 Message-Id: <20180604152941.20374-14-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180604152941.20374-1-peter.maydell@linaro.org> References: <20180604152941.20374-1-peter.maydell@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PATCH v2 13/13] hw/arm/mps2-tz.c: Instantiate MPCs 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: patches@linaro.org, Peter Xu , Eric Auger , Paolo Bonzini , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Instantiate and wire up the Memory Protection Controllers in the MPS2 board itself. Signed-off-by: Peter Maydell Reviewed-by: Alex Benn=C3=A9e --- hw/arm/mps2-tz.c | 71 ++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index 8dc8bfd4ab2..a58b5dea79f 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -44,6 +44,7 @@ #include "hw/timer/cmsdk-apb-timer.h" #include "hw/misc/mps2-scc.h" #include "hw/misc/mps2-fpgaio.h" +#include "hw/misc/tz-mpc.h" #include "hw/arm/iotkit.h" #include "hw/devices.h" #include "net/net.h" @@ -64,13 +65,12 @@ typedef struct { =20 IoTKit iotkit; MemoryRegion psram; - MemoryRegion ssram1; + MemoryRegion ssram[3]; MemoryRegion ssram1_m; - MemoryRegion ssram23; MPS2SCC scc; MPS2FPGAIO fpgaio; TZPPC ppc[5]; - UnimplementedDeviceState ssram_mpc[3]; + TZMPC ssram_mpc[3]; UnimplementedDeviceState spi[5]; UnimplementedDeviceState i2c[4]; UnimplementedDeviceState i2s_audio; @@ -95,16 +95,6 @@ typedef struct { /* Main SYSCLK frequency in Hz */ #define SYSCLK_FRQ 20000000 =20 -/* Initialize the auxiliary RAM region @mr and map it into - * the memory map at @base. - */ -static void make_ram(MemoryRegion *mr, const char *name, - hwaddr base, hwaddr size) -{ - memory_region_init_ram(mr, NULL, name, size, &error_fatal); - memory_region_add_subregion(get_system_memory(), base, mr); -} - /* Create an alias of an entire original MemoryRegion @orig * located at @base in the memory map. */ @@ -224,6 +214,44 @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *m= ms, void *opaque, return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0); } =20 +static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque, + const char *name, hwaddr size) +{ + TZMPC *mpc =3D opaque; + int i =3D mpc - &mms->ssram_mpc[0]; + MemoryRegion *ssram =3D &mms->ssram[i]; + MemoryRegion *upstream; + char *mpcname =3D g_strdup_printf("%s-mpc", name); + static uint32_t ramsize[] =3D { 0x00400000, 0x00200000, 0x00200000 }; + static uint32_t rambase[] =3D { 0x00000000, 0x28000000, 0x28200000 }; + + memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal); + + init_sysbus_child(OBJECT(mms), mpcname, mpc, + sizeof(mms->ssram_mpc[0]), TYPE_TZ_MPC); + object_property_set_link(OBJECT(mpc), OBJECT(ssram), + "downstream", &error_fatal); + object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal); + /* Map the upstream end of the MPC into system memory */ + upstream =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1); + memory_region_add_subregion(get_system_memory(), rambase[i], upstream); + /* and connect its interrupt to the IoTKit */ + qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0, + qdev_get_gpio_in_named(DEVICE(&mms->iotkit= ), + "mpcexp_status", i)= ); + + /* The first SSRAM is a special case as it has an alias; accesses to + * the alias region at 0x00400000 must also go to the MPC upstream. + */ + if (i =3D=3D 0) { + make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x0040000= 0); + } + + g_free(mpcname); + /* Return the register interface MR for our caller to map behind the P= PC */ + return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); +} + static void mps2tz_common_init(MachineState *machine) { MPS2TZMachineState *mms =3D MPS2TZ_MACHINE(machine); @@ -285,14 +313,6 @@ static void mps2tz_common_init(MachineState *machine) NULL, "mps.ram", 0x01000000); memory_region_add_subregion(system_memory, 0x80000000, &mms->psram); =20 - /* The SSRAM memories should all be behind Memory Protection Controlle= rs, - * but we don't implement that yet. - */ - make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000); - make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x0040000= 0); - - make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000); - /* The overflow IRQs for all UARTs are ORed together. * Tx, Rx and "combined" IRQs are sent to the NVIC separately. * Create the OR gate for this. @@ -322,12 +342,9 @@ static void mps2tz_common_init(MachineState *machine) const PPCInfo ppcs[] =3D { { .name =3D "apb_ppcexp0", .ports =3D { - { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0], - 0x58007000, 0x1000 }, - { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1], - 0x58008000, 0x1000 }, - { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2], - 0x58009000, 0x1000 }, + { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1= 000 }, + { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1= 000 }, + { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1= 000 }, }, }, { .name =3D "apb_ppcexp1", --=20 2.17.1