From nobody Sat Jun 28 14:01:45 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1519150650649848.4779481997545; Tue, 20 Feb 2018 10:17:30 -0800 (PST) Received: from localhost ([::1]:57042 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eoCTj-0003tw-NO for importer@patchew.org; Tue, 20 Feb 2018 13:17:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54064) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eoCGd-0008Hi-9g for qemu-devel@nongnu.org; Tue, 20 Feb 2018 13:03:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eoCGb-0001lH-65 for qemu-devel@nongnu.org; Tue, 20 Feb 2018 13:03:51 -0500 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:46524) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eoCGV-0001WQ-7y; Tue, 20 Feb 2018 13:03:43 -0500 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1eoCGH-0008Qx-AI; Tue, 20 Feb 2018 18:03:29 +0000 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Tue, 20 Feb 2018 18:03:10 +0000 Message-Id: <20180220180325.29818-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180220180325.29818-1-peter.maydell@linaro.org> References: <20180220180325.29818-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 04/19] target/arm: Define an IDAU interface 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 Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In v8M, the Implementation Defined Attribution Unit (IDAU) is a small piece of hardware typically implemented in the SoC which provides board or SoC specific security attribution information for each address that the CPU performs MPU/SAU checks on. For QEMU, we model this with a QOM interface which is implemented by the board or SoC object and connected to the CPU using a link property. This commit defines the new interface class, adds the link property to the CPU object, and makes the SAU checking code call the IDAU interface if one is present. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson --- An example of an object that implements the IDAU can be found in the later patch "hw/arm/iotkit: Model Arm IOT Kit". --- target/arm/cpu.h | 3 +++ target/arm/idau.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++= ++++ target/arm/cpu.c | 15 +++++++++++++ target/arm/helper.c | 28 +++++++++++++++++++++--- 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 target/arm/idau.h diff --git a/target/arm/cpu.h b/target/arm/cpu.h index de62df091c..dc45b740c5 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -685,6 +685,9 @@ struct ARMCPU { /* MemoryRegion to use for secure physical accesses */ MemoryRegion *secure_memory; =20 + /* For v8M, pointer to the IDAU interface provided by board/SoC */ + Object *idau; + /* 'compatible' string for this CPU for Linux device trees */ const char *dtb_compatible; =20 diff --git a/target/arm/idau.h b/target/arm/idau.h new file mode 100644 index 0000000000..cac27b95fa --- /dev/null +++ b/target/arm/idau.h @@ -0,0 +1,61 @@ +/* + * QEMU ARM CPU -- interface for the Arm v8M IDAU + * + * Copyright (c) 2018 Linaro Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see + * + * + * In the v8M architecture, the IDAU is a small piece of hardware + * typically implemented in the SoC which provides board or SoC + * specific security attribution information for each address that + * the CPU performs MPU/SAU checks on. For QEMU, we model this with a + * QOM interface which is implemented by the board or SoC object and + * connected to the CPU using a link property. + */ + +#ifndef TARGET_ARM_IDAU_H +#define TARGET_ARM_IDAU_H + +#include "qom/object.h" + +#define TYPE_IDAU_INTERFACE "idau-interface" +#define IDAU_INTERFACE(obj) \ + INTERFACE_CHECK(IDAUInterface, (obj), TYPE_IDAU_INTERFACE) +#define IDAU_INTERFACE_CLASS(class) \ + OBJECT_CLASS_CHECK(IDAUInterfaceClass, (class), TYPE_IDAU_INTERFACE) +#define IDAU_INTERFACE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(IDAUInterfaceClass, (obj), TYPE_IDAU_INTERFACE) + +typedef struct IDAUInterface { + Object parent; +} IDAUInterface; + +#define IREGION_NOTVALID -1 + +typedef struct IDAUInterfaceClass { + InterfaceClass parent; + + /* Check the specified address and return the IDAU security information + * for it by filling in iregion, exempt, ns and nsc: + * iregion: IDAU region number, or IREGION_NOTVALID if not valid + * exempt: true if address is exempt from security attribution + * ns: true if the address is NonSecure + * nsc: true if the address is NonSecure-callable + */ + void (*check)(IDAUInterface *ii, uint32_t address, int *iregion, + bool *exempt, bool *ns, bool *nsc); +} IDAUInterfaceClass; + +#endif diff --git a/target/arm/cpu.c b/target/arm/cpu.c index d796085be9..99d00c3ac9 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -19,6 +19,7 @@ */ =20 #include "qemu/osdep.h" +#include "target/arm/idau.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "cpu.h" @@ -687,6 +688,13 @@ static void arm_cpu_post_init(Object *obj) } } =20 + if (arm_feature(&cpu->env, ARM_FEATURE_M_SECURITY)) { + object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, &cpu->i= dau, + qdev_prop_allow_set_link_before_realize, + OBJ_PROP_LINK_UNREF_ON_RELEASE, + &error_abort); + } + qdev_property_add_static(DEVICE(obj), &arm_cpu_cfgend_property, &error_abort); } @@ -1820,11 +1828,18 @@ static const TypeInfo arm_cpu_type_info =3D { .class_init =3D arm_cpu_class_init, }; =20 +static const TypeInfo idau_interface_type_info =3D { + .name =3D TYPE_IDAU_INTERFACE, + .parent =3D TYPE_INTERFACE, + .class_size =3D sizeof(IDAUInterfaceClass), +}; + static void arm_cpu_register_types(void) { const ARMCPUInfo *info =3D arm_cpus; =20 type_register_static(&arm_cpu_type_info); + type_register_static(&idau_interface_type_info); =20 while (info->name) { cpu_register(info); diff --git a/target/arm/helper.c b/target/arm/helper.c index e7586fcf6c..3acbcb2a1a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "target/arm/idau.h" #include "trace.h" #include "cpu.h" #include "internals.h" @@ -9740,19 +9741,32 @@ static void v8m_security_lookup(CPUARMState *env, u= int32_t address, */ ARMCPU *cpu =3D arm_env_get_cpu(env); int r; + bool idau_exempt =3D false, idau_ns =3D true, idau_nsc =3D true; + int idau_region =3D IREGION_NOTVALID; =20 - /* TODO: implement IDAU */ + if (cpu->idau) { + IDAUInterfaceClass *iic =3D IDAU_INTERFACE_GET_CLASS(cpu->idau); + IDAUInterface *ii =3D IDAU_INTERFACE(cpu->idau); + + iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns, + &idau_nsc); + } =20 if (access_type =3D=3D MMU_INST_FETCH && extract32(address, 28, 4) =3D= =3D 0xf) { /* 0xf0000000..0xffffffff is always S for insn fetches */ return; } =20 - if (v8m_is_sau_exempt(env, address, access_type)) { + if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) { sattrs->ns =3D !regime_is_secure(env, mmu_idx); return; } =20 + if (idau_region !=3D IREGION_NOTVALID) { + sattrs->irvalid =3D true; + sattrs->iregion =3D idau_region; + } + switch (env->sau.ctrl & 3) { case 0: /* SAU.ENABLE =3D=3D 0, SAU.ALLNS =3D=3D 0 */ break; @@ -9789,7 +9803,15 @@ static void v8m_security_lookup(CPUARMState *env, ui= nt32_t address, } } =20 - /* TODO when we support the IDAU then it may override the result h= ere */ + /* The IDAU will override the SAU lookup results if it specifies + * higher security than the SAU does. + */ + if (!idau_ns) { + if (sattrs->ns || (!idau_nsc && sattrs->nsc)) { + sattrs->ns =3D false; + sattrs->nsc =3D idau_nsc; + } + } break; } } --=20 2.16.1