From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820565431391.21347553941655; Thu, 9 Aug 2018 06:16:05 -0700 (PDT) Received: from localhost ([::1]:50789 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnknF-0003IQ-Tw for importer@patchew.org; Thu, 09 Aug 2018 09:15:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47408) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZa-00064h-2J for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZU-0003SX-Pj for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:50 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44194) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZI-00038J-2T; Thu, 09 Aug 2018 09:01:32 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZ5-0003Ey-PY; Thu, 09 Aug 2018 14:01:19 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:00 +0100 Message-Id: <20180809130115.28951-2-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 01/16] hw/watchdog/cmsdk_apb_watchdog: Implement CMSDK APB watchdog module 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The Arm Cortex-M System Design Kit includes a simple watchdog module based on a 32-bit down-counter. Implement this. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- Makefile.objs | 1 + hw/watchdog/Makefile.objs | 1 + include/hw/watchdog/cmsdk-apb-watchdog.h | 59 ++++ hw/watchdog/cmsdk-apb-watchdog.c | 326 +++++++++++++++++++++++ MAINTAINERS | 2 + default-configs/arm-softmmu.mak | 1 + hw/watchdog/trace-events | 6 + 7 files changed, 396 insertions(+) create mode 100644 include/hw/watchdog/cmsdk-apb-watchdog.h create mode 100644 hw/watchdog/cmsdk-apb-watchdog.c create mode 100644 hw/watchdog/trace-events diff --git a/Makefile.objs b/Makefile.objs index 7a9828da282..ce9c79235e6 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -240,6 +240,7 @@ trace-events-subdirs +=3D hw/tpm trace-events-subdirs +=3D hw/usb trace-events-subdirs +=3D hw/vfio trace-events-subdirs +=3D hw/virtio +trace-events-subdirs +=3D hw/watchdog trace-events-subdirs +=3D hw/xen trace-events-subdirs +=3D io trace-events-subdirs +=3D linux-user diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs index 9589bed63a3..3f536d1cad8 100644 --- a/hw/watchdog/Makefile.objs +++ b/hw/watchdog/Makefile.objs @@ -1,4 +1,5 @@ common-obj-y +=3D watchdog.o +common-obj-$(CONFIG_CMSDK_APB_WATCHDOG) +=3D cmsdk-apb-watchdog.o common-obj-$(CONFIG_WDT_IB6300ESB) +=3D wdt_i6300esb.o common-obj-$(CONFIG_WDT_IB700) +=3D wdt_ib700.o common-obj-$(CONFIG_WDT_DIAG288) +=3D wdt_diag288.o diff --git a/include/hw/watchdog/cmsdk-apb-watchdog.h b/include/hw/watchdog= /cmsdk-apb-watchdog.h new file mode 100644 index 00000000000..ab8b5987a19 --- /dev/null +++ b/include/hw/watchdog/cmsdk-apb-watchdog.h @@ -0,0 +1,59 @@ +/* + * ARM CMSDK APB watchdog 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 "APB watchdog" which is part of the Cortex-M + * System Design Kit (CMSDK) and documented in the Cortex-M System + * Design Kit Technical Reference Manual (ARM DDI0479C): + * https://developer.arm.com/products/system-design/system-design-kits/cor= tex-m-system-design-kit + * + * QEMU interface: + * + QOM property "wdogclk-frq": frequency at which the watchdog is clock= ed + * + sysbus MMIO region 0: the register bank + * + sysbus IRQ 0: watchdog interrupt + * + * In real hardware the watchdog's reset output is just a GPIO line + * which can then be masked by the board or treated as a simple interrupt. + * (For instance the IoTKit does this with the non-secure watchdog, so that + * secure code can control whether non-secure code can perform a system + * reset via its watchdog.) In QEMU, we just wire up the watchdog reset + * to watchdog_perform_action(), at least for the moment. + */ + +#ifndef CMSDK_APB_WATCHDOG_H +#define CMSDK_APB_WATCHDOG_H + +#include "hw/sysbus.h" +#include "hw/ptimer.h" + +#define TYPE_CMSDK_APB_WATCHDOG "cmsdk-apb-watchdog" +#define CMSDK_APB_WATCHDOG(obj) OBJECT_CHECK(CMSDKAPBWatchdog, (obj), \ + TYPE_CMSDK_APB_WATCHDOG) + +typedef struct CMSDKAPBWatchdog { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion iomem; + qemu_irq wdogint; + uint32_t wdogclk_frq; + struct ptimer_state *timer; + + uint32_t control; + uint32_t intstatus; + uint32_t lock; + uint32_t itcr; + uint32_t itop; + uint32_t resetstatus; +} CMSDKAPBWatchdog; + +#endif diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watch= dog.c new file mode 100644 index 00000000000..eb79a73fa6c --- /dev/null +++ b/hw/watchdog/cmsdk-apb-watchdog.c @@ -0,0 +1,326 @@ +/* + * ARM CMSDK APB watchdog 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 "APB watchdog" which is part of the Cortex-M + * System Design Kit (CMSDK) and documented in the Cortex-M System + * Design Kit Technical Reference Manual (ARM DDI0479C): + * https://developer.arm.com/products/system-design/system-design-kits/cor= tex-m-system-design-kit + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "trace.h" +#include "qapi/error.h" +#include "qemu/main-loop.h" +#include "sysemu/watchdog.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/watchdog/cmsdk-apb-watchdog.h" + +REG32(WDOGLOAD, 0x0) +REG32(WDOGVALUE, 0x4) +REG32(WDOGCONTROL, 0x8) + FIELD(WDOGCONTROL, INTEN, 0, 1) + FIELD(WDOGCONTROL, RESEN, 1, 1) +#define R_WDOGCONTROL_VALID_MASK (R_WDOGCONTROL_INTEN_MASK | \ + R_WDOGCONTROL_RESEN_MASK) +REG32(WDOGINTCLR, 0xc) +REG32(WDOGRIS, 0x10) + FIELD(WDOGRIS, INT, 0, 1) +REG32(WDOGMIS, 0x14) +REG32(WDOGLOCK, 0xc00) +#define WDOG_UNLOCK_VALUE 0x1ACCE551 +REG32(WDOGITCR, 0xf00) + FIELD(WDOGITCR, ENABLE, 0, 1) +#define R_WDOGITCR_VALID_MASK R_WDOGITCR_ENABLE_MASK +REG32(WDOGITOP, 0xf04) + FIELD(WDOGITOP, WDOGRES, 0, 1) + FIELD(WDOGITOP, WDOGINT, 1, 1) +#define R_WDOGITOP_VALID_MASK (R_WDOGITOP_WDOGRES_MASK | \ + R_WDOGITOP_WDOGINT_MASK) +REG32(PID4, 0xfd0) +REG32(PID5, 0xfd4) +REG32(PID6, 0xfd8) +REG32(PID7, 0xfdc) +REG32(PID0, 0xfe0) +REG32(PID1, 0xfe4) +REG32(PID2, 0xfe8) +REG32(PID3, 0xfec) +REG32(CID0, 0xff0) +REG32(CID1, 0xff4) +REG32(CID2, 0xff8) +REG32(CID3, 0xffc) + +/* PID/CID values */ +static const int watchdog_id[] =3D { + 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ + 0x24, 0xb8, 0x1b, 0x00, /* PID0..PID3 */ + 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ +}; + +static bool cmsdk_apb_watchdog_intstatus(CMSDKAPBWatchdog *s) +{ + /* Return masked interrupt status */ + return s->intstatus && (s->control & R_WDOGCONTROL_INTEN_MASK); +} + +static bool cmsdk_apb_watchdog_resetstatus(CMSDKAPBWatchdog *s) +{ + /* Return masked reset status */ + return s->resetstatus && (s->control & R_WDOGCONTROL_RESEN_MASK); +} + +static void cmsdk_apb_watchdog_update(CMSDKAPBWatchdog *s) +{ + bool wdogint; + bool wdogres; + + if (s->itcr) { + wdogint =3D s->itop & R_WDOGITOP_WDOGINT_MASK; + wdogres =3D s->itop & R_WDOGITOP_WDOGRES_MASK; + } else { + wdogint =3D cmsdk_apb_watchdog_intstatus(s); + wdogres =3D cmsdk_apb_watchdog_resetstatus(s); + } + + qemu_set_irq(s->wdogint, wdogint); + if (wdogres) { + watchdog_perform_action(); + } +} + +static uint64_t cmsdk_apb_watchdog_read(void *opaque, hwaddr offset, + unsigned size) +{ + CMSDKAPBWatchdog *s =3D CMSDK_APB_WATCHDOG(opaque); + uint64_t r; + + switch (offset) { + case A_WDOGLOAD: + r =3D ptimer_get_limit(s->timer); + break; + case A_WDOGVALUE: + r =3D ptimer_get_count(s->timer); + break; + case A_WDOGCONTROL: + r =3D s->control; + break; + case A_WDOGRIS: + r =3D s->intstatus; + break; + case A_WDOGMIS: + r =3D cmsdk_apb_watchdog_intstatus(s); + break; + case A_WDOGLOCK: + r =3D s->lock; + break; + case A_WDOGITCR: + r =3D s->itcr; + break; + case A_PID4 ... A_CID3: + r =3D watchdog_id[(offset - A_PID4) / 4]; + break; + case A_WDOGINTCLR: + case A_WDOGITOP: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB watchdog read: read of WO offset %x\n", + (int)offset); + r =3D 0; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB watchdog read: bad offset %x\n", (int)off= set); + r =3D 0; + break; + } + trace_cmsdk_apb_watchdog_read(offset, r, size); + return r; +} + +static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + CMSDKAPBWatchdog *s =3D CMSDK_APB_WATCHDOG(opaque); + + trace_cmsdk_apb_watchdog_write(offset, value, size); + + if (s->lock && offset !=3D A_WDOGLOCK) { + /* Write access is disabled via WDOGLOCK */ + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB watchdog write: write to locked watchdog\= n"); + return; + } + + switch (offset) { + case A_WDOGLOAD: + /* + * Reset the load value and the current count, and make sure + * we're counting. + */ + ptimer_set_limit(s->timer, value, 1); + ptimer_run(s->timer, 0); + break; + case A_WDOGCONTROL: + s->control =3D value & R_WDOGCONTROL_VALID_MASK; + cmsdk_apb_watchdog_update(s); + break; + case A_WDOGINTCLR: + s->intstatus =3D 0; + ptimer_set_count(s->timer, ptimer_get_limit(s->timer)); + cmsdk_apb_watchdog_update(s); + break; + case A_WDOGLOCK: + s->lock =3D (value !=3D WDOG_UNLOCK_VALUE); + break; + case A_WDOGITCR: + s->itcr =3D value & R_WDOGITCR_VALID_MASK; + cmsdk_apb_watchdog_update(s); + break; + case A_WDOGITOP: + s->itop =3D value & R_WDOGITOP_VALID_MASK; + cmsdk_apb_watchdog_update(s); + break; + case A_WDOGVALUE: + case A_WDOGRIS: + case A_WDOGMIS: + case A_PID4 ... A_CID3: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB watchdog write: write to RO offset 0x%x\n= ", + (int)offset); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "CMSDK APB watchdog write: bad offset 0x%x\n", + (int)offset); + break; + } +} + +static const MemoryRegionOps cmsdk_apb_watchdog_ops =3D { + .read =3D cmsdk_apb_watchdog_read, + .write =3D cmsdk_apb_watchdog_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + /* byte/halfword accesses are just zero-padded on reads and writes */ + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 4, +}; + +static void cmsdk_apb_watchdog_tick(void *opaque) +{ + CMSDKAPBWatchdog *s =3D CMSDK_APB_WATCHDOG(opaque); + + if (!s->intstatus) { + /* Count expired for the first time: raise interrupt */ + s->intstatus =3D R_WDOGRIS_INT_MASK; + } else { + /* Count expired for the second time: raise reset and stop clock */ + s->resetstatus =3D 1; + ptimer_stop(s->timer); + } + cmsdk_apb_watchdog_update(s); +} + +static void cmsdk_apb_watchdog_reset(DeviceState *dev) +{ + CMSDKAPBWatchdog *s =3D CMSDK_APB_WATCHDOG(dev); + + trace_cmsdk_apb_watchdog_reset(); + s->control =3D 0; + s->intstatus =3D 0; + s->lock =3D 0; + s->itcr =3D 0; + s->itop =3D 0; + s->resetstatus =3D 0; + /* Set the limit and the count */ + ptimer_set_limit(s->timer, 0xffffffff, 1); + ptimer_run(s->timer, 0); +} + +static void cmsdk_apb_watchdog_init(Object *obj) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + CMSDKAPBWatchdog *s =3D CMSDK_APB_WATCHDOG(obj); + + memory_region_init_io(&s->iomem, obj, &cmsdk_apb_watchdog_ops, + s, "cmsdk-apb-watchdog", 0x1000); + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_irq(sbd, &s->wdogint); +} + +static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp) +{ + CMSDKAPBWatchdog *s =3D CMSDK_APB_WATCHDOG(dev); + QEMUBH *bh; + + if (s->wdogclk_frq =3D=3D 0) { + error_setg(errp, + "CMSDK APB watchdog: wdogclk-frq property must be set"); + return; + } + + bh =3D qemu_bh_new(cmsdk_apb_watchdog_tick, s); + s->timer =3D ptimer_init(bh, + PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | + PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT | + PTIMER_POLICY_NO_IMMEDIATE_RELOAD | + PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); + + ptimer_set_freq(s->timer, s->wdogclk_frq); +} + +static const VMStateDescription cmsdk_apb_watchdog_vmstate =3D { + .name =3D "cmsdk-apb-watchdog", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_PTIMER(timer, CMSDKAPBWatchdog), + VMSTATE_UINT32(control, CMSDKAPBWatchdog), + VMSTATE_UINT32(intstatus, CMSDKAPBWatchdog), + VMSTATE_UINT32(lock, CMSDKAPBWatchdog), + VMSTATE_UINT32(itcr, CMSDKAPBWatchdog), + VMSTATE_UINT32(itop, CMSDKAPBWatchdog), + VMSTATE_UINT32(resetstatus, CMSDKAPBWatchdog), + VMSTATE_END_OF_LIST() + } +}; + +static Property cmsdk_apb_watchdog_properties[] =3D { + DEFINE_PROP_UINT32("wdogclk-frq", CMSDKAPBWatchdog, wdogclk_frq, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D cmsdk_apb_watchdog_realize; + dc->vmsd =3D &cmsdk_apb_watchdog_vmstate; + dc->reset =3D cmsdk_apb_watchdog_reset; + dc->props =3D cmsdk_apb_watchdog_properties; +} + +static const TypeInfo cmsdk_apb_watchdog_info =3D { + .name =3D TYPE_CMSDK_APB_WATCHDOG, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(CMSDKAPBWatchdog), + .instance_init =3D cmsdk_apb_watchdog_init, + .class_init =3D cmsdk_apb_watchdog_class_init, +}; + +static void cmsdk_apb_watchdog_register_types(void) +{ + type_register_static(&cmsdk_apb_watchdog_info); +} + +type_init(cmsdk_apb_watchdog_register_types); diff --git a/MAINTAINERS b/MAINTAINERS index 2c1a55ca207..7ea39c0176b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -457,6 +457,8 @@ F: hw/timer/cmsdk-apb-dualtimer.c F: include/hw/timer/cmsdk-apb-dualtimer.h F: hw/char/cmsdk-apb-uart.c F: include/hw/char/cmsdk-apb-uart.h +F: hw/watchdog/cmsdk-apb-watchdog.c +F: include/hw/watchdog/cmsdk-apb-watchdog.h F: hw/misc/tz-ppc.c F: include/hw/misc/tz-ppc.h F: hw/misc/tz-mpc.c diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.= mak index 046e8903839..521c3d459fa 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -105,6 +105,7 @@ CONFIG_STM32F205_SOC=3Dy CONFIG_CMSDK_APB_TIMER=3Dy CONFIG_CMSDK_APB_DUALTIMER=3Dy CONFIG_CMSDK_APB_UART=3Dy +CONFIG_CMSDK_APB_WATCHDOG=3Dy =20 CONFIG_MPS2_FPGAIO=3Dy CONFIG_MPS2_SCC=3Dy diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events new file mode 100644 index 00000000000..fee95847df0 --- /dev/null +++ b/hw/watchdog/trace-events @@ -0,0 +1,6 @@ +# See docs/devel/tracing.txt for syntax documentation. + +# hw/char/cmsdk_apb_watchdog.c +cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CM= SDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "C= MSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset" --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820078600834.2357231645138; Thu, 9 Aug 2018 06:07:58 -0700 (PDT) Received: from localhost ([::1]:50739 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkfV-0002hV-DM for importer@patchew.org; Thu, 09 Aug 2018 09:07:57 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47337) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZW-00061v-D3 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZS-0003QS-9M for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:46 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44214) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZH-0003Gd-G7; Thu, 09 Aug 2018 09:01:31 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZ6-0003FV-P9; Thu, 09 Aug 2018 14:01:20 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:01 +0100 Message-Id: <20180809130115.28951-3-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 02/16] nvic: Expose NMI line 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" On real v7M hardware, the NMI line is an externally visible signal that an SoC or board can toggle to assert an NMI. Expose it in our QEMU NVIC and armv7m container objects so that a board model can wire it up if it needs to. In particular, the MPS2 watchdog is wired to NMI. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/arm/armv7m.c | 1 + hw/intc/armv7m_nvic.c | 19 +++++++++++++++++++ hw/intc/trace-events | 1 + 3 files changed, 21 insertions(+) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 6b076660574..66217a6053a 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -202,6 +202,7 @@ static void armv7m_realize(DeviceState *dev, Error **er= rp) */ qdev_pass_gpios(DEVICE(&s->nvic), dev, NULL); qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ"); + qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI"); =20 /* Wire the NVIC up to the CPU */ sbd =3D SYS_BUS_DEVICE(&s->nvic); diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index cd1e7f17299..be7771e9d1f 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -772,6 +772,24 @@ static void set_irq_level(void *opaque, int n, int lev= el) } } =20 +/* callback when external NMI line is changed */ +static void nvic_nmi_trigger(void *opaque, int n, int level) +{ + NVICState *s =3D opaque; + + trace_nvic_set_nmi_level(level); + + /* + * The architecture doesn't specify whether NMI should share + * the normal-interrupt behaviour of being resampled on + * exception handler return. We choose not to, so just + * set NMI pending here and don't track the current level. + */ + if (level) { + armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI, false); + } +} + static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs) { ARMCPU *cpu =3D s->cpu; @@ -2310,6 +2328,7 @@ static void armv7m_nvic_instance_init(Object *obj) qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1); qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger", M_REG_NUM_BANKS); + qdev_init_gpio_in_named(dev, nvic_nmi_trigger, "NMI", 1); } =20 static void armv7m_nvic_class_init(ObjectClass *klass, void *data) diff --git a/hw/intc/trace-events b/hw/intc/trace-events index 5fb18e65c97..33e932fb918 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -184,6 +184,7 @@ nvic_acknowledge_irq(int irq, int prio) "NVIC acknowled= ge IRQ: %d now active (pr nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets= _secure: %d" nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)" nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to = %d" +nvic_set_nmi_level(int level) "NVIC external NMI level set to %d" nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysre= g read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysr= eg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u" =20 --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820257966242.22293711234101; Thu, 9 Aug 2018 06:10:57 -0700 (PDT) Received: from localhost ([::1]:50760 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkiL-0005uD-6T for importer@patchew.org; Thu, 09 Aug 2018 09:10:53 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47396) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZZ-00064e-7M for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZY-0003Ze-1h for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:49 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44220) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZH-0003Hp-AF; Thu, 09 Aug 2018 09:01:31 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZ7-0003G1-Lf; Thu, 09 Aug 2018 14:01:21 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:02 +0100 Message-Id: <20180809130115.28951-4-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 03/16] hw/arm/iotkit: Wire up the watchdogs 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The IoTKit includes three different instances of the CMSDK APB watchdog; create and wire them up. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/arm/iotkit.h | 6 +++++ hw/arm/iotkit.c | 58 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h index 3e6d806e352..776d0497087 100644 --- a/include/hw/arm/iotkit.h +++ b/include/hw/arm/iotkit.h @@ -57,6 +57,7 @@ #include "hw/misc/tz-mpc.h" #include "hw/timer/cmsdk-apb-timer.h" #include "hw/timer/cmsdk-apb-dualtimer.h" +#include "hw/watchdog/cmsdk-apb-watchdog.h" #include "hw/misc/unimp.h" #include "hw/or-irq.h" #include "hw/core/split-irq.h" @@ -87,10 +88,15 @@ typedef struct IoTKit { SplitIRQ ppc_irq_splitter[NUM_PPCS]; SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC]; qemu_or_irq mpc_irq_orgate; + qemu_or_irq nmi_orgate; =20 CMSDKAPBDualTimer dualtimer; UnimplementedDeviceState s32ktimer; =20 + CMSDKAPBWatchdog s32kwatchdog; + CMSDKAPBWatchdog nswatchdog; + CMSDKAPBWatchdog swatchdog; + MemoryRegion container; MemoryRegion alias1; MemoryRegion alias2; diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c index 130d013909e..5cedfa03570 100644 --- a/hw/arm/iotkit.c +++ b/hw/arm/iotkit.c @@ -19,6 +19,9 @@ #include "hw/misc/unimp.h" #include "hw/arm/arm.h" =20 +/* Clock frequency in HZ of the 32KHz "slow clock" */ +#define S32KCLK (32 * 1000) + /* Create an alias region of @size bytes starting at @base * which mirrors the memory starting at @orig. */ @@ -140,6 +143,15 @@ static void iotkit_init(Object *obj) TYPE_CMSDK_APB_TIMER); sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualt= imer), TYPE_CMSDK_APB_DUALTIMER); + sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog, + sizeof(s->s32kwatchdog), TYPE_CMSDK_APB_WATCHDOG= ); + sysbus_init_child_obj(obj, "nswatchdog", &s->nswatchdog, + sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG); + sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog, + sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG); + object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, + sizeof(s->nmi_orgate), TYPE_OR_IRQ, + &error_abort, NULL); object_initialize_child(obj, "ppc-irq-orgate", &s->ppc_irq_orgate, sizeof(s->ppc_irq_orgate), TYPE_OR_IRQ, &error_abort, NULL); @@ -510,12 +522,52 @@ static void iotkit_realize(DeviceState *dev, Error **= errp) create_unimplemented_device("SYSINFO", 0x40020000, 0x1000); =20 create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000); - create_unimplemented_device("S32KWATCHDOG", 0x5002e000, 0x1000); + + /* This OR gate wires together outputs from the secure watchdogs to NM= I */ + object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err); + if (err) { + error_propagate(errp, err); + return; + } + object_property_set_bool(OBJECT(&s->nmi_orgate), true, "realized", &er= r); + if (err) { + error_propagate(errp, err); + return; + } + qdev_connect_gpio_out(DEVICE(&s->nmi_orgate), 0, + qdev_get_gpio_in_named(DEVICE(&s->armv7m), "NMI"= , 0)); + + qdev_prop_set_uint32(DEVICE(&s->s32kwatchdog), "wdogclk-frq", S32KCLK); + object_property_set_bool(OBJECT(&s->s32kwatchdog), true, "realized", &= err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, + qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 0)); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->s32kwatchdog), 0, 0x5002e000); =20 /* 0x40080000 .. 0x4008ffff : IoTKit second Base peripheral region */ =20 - create_unimplemented_device("NS watchdog", 0x40081000, 0x1000); - create_unimplemented_device("S watchdog", 0x50081000, 0x1000); + qdev_prop_set_uint32(DEVICE(&s->nswatchdog), "wdogclk-frq", s->mainclk= _frq); + object_property_set_bool(OBJECT(&s->nswatchdog), true, "realized", &er= r); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_connect_irq(SYS_BUS_DEVICE(&s->nswatchdog), 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), 1)); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->nswatchdog), 0, 0x40081000); + + qdev_prop_set_uint32(DEVICE(&s->swatchdog), "wdogclk-frq", s->mainclk_= frq); + object_property_set_bool(OBJECT(&s->swatchdog), true, "realized", &err= ); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_connect_irq(SYS_BUS_DEVICE(&s->swatchdog), 0, + qdev_get_gpio_in(DEVICE(&s->nmi_orgate), 1)); + sysbus_mmio_map(SYS_BUS_DEVICE(&s->swatchdog), 0, 0x50081000); =20 for (i =3D 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) { Object *splitter =3D OBJECT(&s->ppc_irq_splitter[i]); --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820037644514.8599300959842; Thu, 9 Aug 2018 06:07:17 -0700 (PDT) Received: from localhost ([::1]:50735 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkeq-0001tY-Fs for importer@patchew.org; Thu, 09 Aug 2018 09:07:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47282) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZU-00060K-VE for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZR-0003P7-0e for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:45 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44194) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZH-00038J-3I; Thu, 09 Aug 2018 09:01:31 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZ8-0003GV-Hn; Thu, 09 Aug 2018 14:01:22 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:03 +0100 Message-Id: <20180809130115.28951-5-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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/16] hw/arm/iotkit: Wire up the S32KTIMER 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The IoTKit has a CMSDK timer device that runs on the S32KCLK. Create this and wire it up. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/arm/iotkit.h | 2 +- hw/arm/iotkit.c | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h index 776d0497087..0f5c5101708 100644 --- a/include/hw/arm/iotkit.h +++ b/include/hw/arm/iotkit.h @@ -83,6 +83,7 @@ typedef struct IoTKit { TZMPC mpc; CMSDKAPBTIMER timer0; CMSDKAPBTIMER timer1; + CMSDKAPBTIMER s32ktimer; qemu_or_irq ppc_irq_orgate; SplitIRQ sec_resp_splitter; SplitIRQ ppc_irq_splitter[NUM_PPCS]; @@ -91,7 +92,6 @@ typedef struct IoTKit { qemu_or_irq nmi_orgate; =20 CMSDKAPBDualTimer dualtimer; - UnimplementedDeviceState s32ktimer; =20 CMSDKAPBWatchdog s32kwatchdog; CMSDKAPBWatchdog nswatchdog; diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c index 5cedfa03570..cb0ec456f39 100644 --- a/hw/arm/iotkit.c +++ b/hw/arm/iotkit.c @@ -141,6 +141,8 @@ static void iotkit_init(Object *obj) TYPE_CMSDK_APB_TIMER); sysbus_init_child_obj(obj, "timer1", &s->timer1, sizeof(s->timer1), TYPE_CMSDK_APB_TIMER); + sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32kt= imer), + TYPE_CMSDK_APB_TIMER); sysbus_init_child_obj(obj, "dualtimer", &s->dualtimer, sizeof(s->dualt= imer), TYPE_CMSDK_APB_DUALTIMER); sysbus_init_child_obj(obj, "s32kwatchdog", &s->s32kwatchdog, @@ -166,8 +168,6 @@ static void iotkit_init(Object *obj) TYPE_SPLIT_IRQ, &error_abort, NULL); g_free(name); } - sysbus_init_child_obj(obj, "s32ktimer", &s->s32ktimer, sizeof(s->s32kt= imer), - TYPE_UNIMPLEMENTED_DEVICE); } =20 static void iotkit_exp_irq(void *opaque, int n, int level) @@ -476,13 +476,14 @@ static void iotkit_realize(DeviceState *dev, Error **= errp) /* Devices behind APB PPC1: * 0x4002f000: S32K timer */ - qdev_prop_set_string(DEVICE(&s->s32ktimer), "name", "S32KTIMER"); - qdev_prop_set_uint64(DEVICE(&s->s32ktimer), "size", 0x1000); + qdev_prop_set_uint32(DEVICE(&s->s32ktimer), "pclk-frq", S32KCLK); object_property_set_bool(OBJECT(&s->s32ktimer), true, "realized", &err= ); if (err) { error_propagate(errp, err); return; } + sysbus_connect_irq(SYS_BUS_DEVICE(&s->s32ktimer), 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), 2)); mr =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->s32ktimer), 0); object_property_set_link(OBJECT(&s->apb_ppc1), OBJECT(mr), "port[0]", = &err); if (err) { --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820524049955.5270416459866; Thu, 9 Aug 2018 06:15:24 -0700 (PDT) Received: from localhost ([::1]:50781 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkmf-0002pL-VB for importer@patchew.org; Thu, 09 Aug 2018 09:15:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47357) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZX-000631-Co for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZR-0003Pe-Lw for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:47 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44214) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZG-0003Gd-Ez; Thu, 09 Aug 2018 09:01:30 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZ9-0003Gy-Fz; Thu, 09 Aug 2018 14:01:23 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:04 +0100 Message-Id: <20180809130115.28951-6-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 05/16] hw/misc/iotkit-sysctl: Implement IoTKit system control element 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The Arm IoTKit includes a system control element which provides a block of read-only ID registers and a block of read-write control registers. Implement a minimal version of this. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/misc/Makefile.objs | 1 + include/hw/misc/iotkit-sysctl.h | 50 +++++ hw/misc/iotkit-sysctl.c | 324 ++++++++++++++++++++++++++++++++ MAINTAINERS | 2 + default-configs/arm-softmmu.mak | 1 + hw/misc/trace-events | 7 + 6 files changed, 385 insertions(+) create mode 100644 include/hw/misc/iotkit-sysctl.h create mode 100644 hw/misc/iotkit-sysctl.c diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 93509008451..dbadb41d57a 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -65,6 +65,7 @@ obj-$(CONFIG_MPS2_SCC) +=3D mps2-scc.o obj-$(CONFIG_TZ_MPC) +=3D tz-mpc.o obj-$(CONFIG_TZ_PPC) +=3D tz-ppc.o obj-$(CONFIG_IOTKIT_SECCTL) +=3D iotkit-secctl.o +obj-$(CONFIG_IOTKIT_SYSCTL) +=3D iotkit-sysctl.o =20 obj-$(CONFIG_PVPANIC) +=3D pvpanic.o obj-$(CONFIG_HYPERV_TESTDEV) +=3D hyperv_testdev.o diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysct= l.h new file mode 100644 index 00000000000..c3b14ccee4c --- /dev/null +++ b/include/hw/misc/iotkit-sysctl.h @@ -0,0 +1,50 @@ +/* + * ARM IoTKit system control element + * + * 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 "system control element" which is part of the + * Arm IoTKit and documented in + * http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.ecm060125= 6/index.html + * Specifically, it implements the "system information block" and + * "system control register" blocks. + * + * QEMU interface: + * + sysbus MMIO region 0: the system information register bank + * + sysbus MMIO region 1: the system control register bank + */ + +#ifndef HW_MISC_IOTKIT_SYSCTL_H +#define HW_MISC_IOTKIT_SYSCTL_H + +#include "hw/sysbus.h" + +#define TYPE_IOTKIT_SYSCTL "iotkit-sysctl" +#define IOTKIT_SYSCTL(obj) OBJECT_CHECK(IoTKitSysCtl, (obj), \ + TYPE_IOTKIT_SYSCTL) + +typedef struct IoTKitSysCtl { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion sysinfo_iomem; + MemoryRegion sysctl_iomem; + + uint32_t secure_debug; + uint32_t reset_syndrome; + uint32_t reset_mask; + uint32_t gretreg; + uint32_t initsvrtor0; + uint32_t cpuwait; + uint32_t wicctrl; +} IoTKitSysCtl; + +#endif diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c new file mode 100644 index 00000000000..9445500be76 --- /dev/null +++ b/hw/misc/iotkit-sysctl.c @@ -0,0 +1,324 @@ +/* + * ARM IoTKit system control element + * + * 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 "system control element" which is part of the + * Arm IoTKit and documented in + * http://infocenter.arm.com/help/index.jsp?topic=3D/com.arm.doc.ecm060125= 6/index.html + * Specifically, it implements the "system information block" and + * "system control register" blocks. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "trace.h" +#include "qapi/error.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" +#include "hw/registerfields.h" +#include "hw/misc/iotkit-sysctl.h" + +/* sysinfo block registers */ +REG32(SYS_VERSION, 0x0) +REG32(SYS_CONFIG, 0x4) + +/* sysctl block registers */ +REG32(SECDBGSTAT, 0x0) +REG32(SECDBGSET, 0x4) +REG32(SECDBGCLR, 0x8) +REG32(RESET_SYNDROME, 0x100) +REG32(RESET_MASK, 0x104) +REG32(SWRESET, 0x108) + FIELD(SWRESET, SWRESETREQ, 9, 1) +REG32(GRETREG, 0x10c) +REG32(INITSVRTOR0, 0x110) +REG32(CPUWAIT, 0x118) +REG32(BUSWAIT, 0x11c) +REG32(WICCTRL, 0x120) + +/* PID registers, same offset in both blocks */ +REG32(PID4, 0xfd0) +REG32(PID5, 0xfd4) +REG32(PID6, 0xfd8) +REG32(PID7, 0xfdc) +REG32(PID0, 0xfe0) +REG32(PID1, 0xfe4) +REG32(PID2, 0xfe8) +REG32(PID3, 0xfec) +REG32(CID0, 0xff0) +REG32(CID1, 0xff4) +REG32(CID2, 0xff8) +REG32(CID3, 0xffc) + +/* PID/CID values */ +static const int sysinfo_id[] =3D { + 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ + 0x58, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ + 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ +}; + +static const int sysctl_id[] =3D { + 0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */ + 0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */ + 0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */ +}; + +static uint64_t iotkit_sysinfo_read(void *opaque, hwaddr offset, + unsigned size) +{ + uint64_t r; + + switch (offset) { + case A_SYS_VERSION: + r =3D 0x41743; + break; + + case A_SYS_CONFIG: + r =3D 0x31; + break; + case A_PID4 ... A_CID3: + r =3D sysinfo_id[(offset - A_PID4) / 4]; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "IoTKit SysInfo read: bad offset %x\n", (int)offset); + r =3D 0; + break; + } + trace_iotkit_sysinfo_read(offset, r, size); + return r; +} + +static void iotkit_sysinfo_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + trace_iotkit_sysinfo_write(offset, value, size); + + qemu_log_mask(LOG_GUEST_ERROR, + "IoTKit SysInfo: write to RO offset 0x%x\n", (int)offset= ); +} + +static const MemoryRegionOps iotkit_sysinfo_ops =3D { + .read =3D iotkit_sysinfo_read, + .write =3D iotkit_sysinfo_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + /* byte/halfword accesses are just zero-padded on reads and writes */ + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 4, +}; + +static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, + unsigned size) +{ + IoTKitSysCtl *s =3D IOTKIT_SYSCTL(opaque); + uint64_t r; + + switch (offset) { + case A_SECDBGSTAT: + r =3D s->secure_debug; + break; + case A_RESET_SYNDROME: + r =3D s->reset_syndrome; + break; + case A_RESET_MASK: + r =3D s->reset_mask; + break; + case A_GRETREG: + r =3D s->gretreg; + break; + case A_INITSVRTOR0: + r =3D s->initsvrtor0; + break; + case A_CPUWAIT: + r =3D s->cpuwait; + break; + case A_BUSWAIT: + /* In IoTKit BUSWAIT is reserved, R/O, zero */ + r =3D 0; + break; + case A_WICCTRL: + r =3D s->wicctrl; + break; + case A_PID4 ... A_CID3: + r =3D sysctl_id[(offset - A_PID4) / 4]; + break; + case A_SECDBGSET: + case A_SECDBGCLR: + case A_SWRESET: + qemu_log_mask(LOG_GUEST_ERROR, + "IoTKit SysCtl read: read of WO offset %x\n", + (int)offset); + r =3D 0; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "IoTKit SysCtl read: bad offset %x\n", (int)offset); + r =3D 0; + break; + } + trace_iotkit_sysctl_read(offset, r, size); + return r; +} + +static void iotkit_sysctl_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + IoTKitSysCtl *s =3D IOTKIT_SYSCTL(opaque); + + trace_iotkit_sysctl_write(offset, value, size); + + /* + * Most of the state here has to do with control of reset and + * similar kinds of power up -- for instance the guest can ask + * what the reason for the last reset was, or forbid reset for + * some causes (like the non-secure watchdog). Most of this is + * not relevant to QEMU, which doesn't really model anything other + * than a full power-on reset. + * We just model the registers as reads-as-written. + */ + + switch (offset) { + case A_RESET_SYNDROME: + qemu_log_mask(LOG_UNIMP, + "IoTKit SysCtl RESET_SYNDROME unimplemented\n"); + s->reset_syndrome =3D value; + break; + case A_RESET_MASK: + qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n= "); + s->reset_mask =3D value; + break; + case A_GRETREG: + /* + * General retention register, which is only reset by a power-on + * reset. Technically this implementation is complete, since + * QEMU only supports power-on resets... + */ + s->gretreg =3D value; + break; + case A_INITSVRTOR0: + qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl INITSVRTOR0 unimplemented\= n"); + s->initsvrtor0 =3D value; + break; + case A_CPUWAIT: + qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CPUWAIT unimplemented\n"); + s->cpuwait =3D value; + break; + case A_WICCTRL: + qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n"); + s->wicctrl =3D value; + break; + case A_SECDBGSET: + /* write-1-to-set */ + qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n"= ); + s->secure_debug |=3D value; + break; + case A_SECDBGCLR: + /* write-1-to-clear */ + s->secure_debug &=3D ~value; + break; + case A_SWRESET: + /* One w/o bit to request a reset; all other bits reserved */ + if (value & R_SWRESET_SWRESETREQ_MASK) { + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + } + break; + case A_BUSWAIT: /* In IoTKit BUSWAIT is reserved, R/O, zero */ + case A_SECDBGSTAT: + case A_PID4 ... A_CID3: + qemu_log_mask(LOG_GUEST_ERROR, + "IoTKit SysCtl write: write of RO offset %x\n", + (int)offset); + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, + "IoTKit SysCtl write: bad offset %x\n", (int)offset); + break; + } +} + +static const MemoryRegionOps iotkit_sysctl_ops =3D { + .read =3D iotkit_sysctl_read, + .write =3D iotkit_sysctl_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + /* byte/halfword accesses are just zero-padded on reads and writes */ + .impl.min_access_size =3D 4, + .impl.max_access_size =3D 4, + .valid.min_access_size =3D 1, + .valid.max_access_size =3D 4, +}; + +static void iotkit_sysctl_reset(DeviceState *dev) +{ + IoTKitSysCtl *s =3D IOTKIT_SYSCTL(dev); + + trace_iotkit_sysctl_reset(); + s->secure_debug =3D 0; + s->reset_syndrome =3D 1; + s->reset_mask =3D 0; + s->gretreg =3D 0; + s->initsvrtor0 =3D 0x10000000; + s->cpuwait =3D 0; + s->wicctrl =3D 0; +} + +static void iotkit_sysctl_init(Object *obj) +{ + SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); + IoTKitSysCtl *s =3D IOTKIT_SYSCTL(obj); + + memory_region_init_io(&s->sysinfo_iomem, obj, &iotkit_sysinfo_ops, + s, "iotkit-sysinfo", 0x1000); + memory_region_init_io(&s->sysctl_iomem, obj, &iotkit_sysctl_ops, + s, "iotkit-sysctl", 0x1000); + sysbus_init_mmio(sbd, &s->sysinfo_iomem); + sysbus_init_mmio(sbd, &s->sysctl_iomem); +} + +static const VMStateDescription iotkit_sysctl_vmstate =3D { + .name =3D "iotkit-sysctl", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(secure_debug, IoTKitSysCtl), + VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl), + VMSTATE_UINT32(reset_mask, IoTKitSysCtl), + VMSTATE_UINT32(gretreg, IoTKitSysCtl), + VMSTATE_UINT32(initsvrtor0, IoTKitSysCtl), + VMSTATE_UINT32(cpuwait, IoTKitSysCtl), + VMSTATE_UINT32(wicctrl, IoTKitSysCtl), + VMSTATE_END_OF_LIST() + } +}; + +static void iotkit_sysctl_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->vmsd =3D &iotkit_sysctl_vmstate; + dc->reset =3D iotkit_sysctl_reset; +} + +static const TypeInfo iotkit_sysctl_info =3D { + .name =3D TYPE_IOTKIT_SYSCTL, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(IoTKitSysCtl), + .instance_init =3D iotkit_sysctl_init, + .class_init =3D iotkit_sysctl_class_init, +}; + +static void iotkit_sysctl_register_types(void) +{ + type_register_static(&iotkit_sysctl_info); +} + +type_init(iotkit_sysctl_register_types); diff --git a/MAINTAINERS b/MAINTAINERS index 7ea39c0176b..96fe011e952 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -537,6 +537,8 @@ F: hw/misc/mps2-*.c F: include/hw/misc/mps2-*.h F: hw/arm/iotkit.c F: include/hw/arm/iotkit.h +F: hw/misc/iotkit-sysctl.c +F: include/hw/misc/iotkit-sysctl.h =20 Musicpal M: Jan Kiszka diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.= mak index 521c3d459fa..da59b820a4f 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -114,6 +114,7 @@ CONFIG_TZ_MPC=3Dy CONFIG_TZ_PPC=3Dy CONFIG_IOTKIT=3Dy CONFIG_IOTKIT_SECCTL=3Dy +CONFIG_IOTKIT_SYSCTL=3Dy =20 CONFIG_VERSATILE=3Dy CONFIG_VERSATILE_PCI=3Dy diff --git a/hw/misc/trace-events b/hw/misc/trace-events index c956e1419b7..83ab58c30f5 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -109,3 +109,10 @@ iotkit_secctl_s_write(uint32_t offset, uint64_t data, = unsigned size) "IoTKit Sec iotkit_secctl_ns_read(uint32_t offset, uint64_t data, unsigned size) "IoTK= it SecCtl NS regs read: offset 0x%x data 0x%" PRIx64 " size %u" iotkit_secctl_ns_write(uint32_t offset, uint64_t data, unsigned size) "IoT= Kit SecCtl NS regs write: offset 0x%x data 0x%" PRIx64 " size %u" iotkit_secctl_reset(void) "IoTKit SecCtl: reset" + +# hw/misc/iotkit-sysctl.c +iotkit_sysinfo_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit= SysInfo read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +iotkit_sysinfo_write(uint64_t offset, uint64_t data, unsigned size) "IoTKi= t SysInfo write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +iotkit_sysctl_read(uint64_t offset, uint64_t data, unsigned size) "IoTKit = SysCtl read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +iotkit_sysctl_write(uint64_t offset, uint64_t data, unsigned size) "IoTKit= SysCtl write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u" +iotkit_sysctl_reset(void) "IoTKit SysCtl: reset" --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153382008923849.28422408800816; Thu, 9 Aug 2018 06:08:09 -0700 (PDT) Received: from localhost ([::1]:50740 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkff-00030f-Tv for importer@patchew.org; Thu, 09 Aug 2018 09:08:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47368) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZY-00063i-1n for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZO-0003NS-L3 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:48 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44214) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZF-0003Gd-GA; Thu, 09 Aug 2018 09:01:29 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZA-0003HQ-Lh; Thu, 09 Aug 2018 14:01:24 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:05 +0100 Message-Id: <20180809130115.28951-7-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 06/16] hw/misc/iotkit: Wire up the system control element 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Wire up the system control element's register banks. This is the last of the previously completely unimplemented components in the IoTKit. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/arm/iotkit.h | 4 +++- hw/arm/iotkit.c | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h index 0f5c5101708..1ffa31d521b 100644 --- a/include/hw/arm/iotkit.h +++ b/include/hw/arm/iotkit.h @@ -58,7 +58,7 @@ #include "hw/timer/cmsdk-apb-timer.h" #include "hw/timer/cmsdk-apb-dualtimer.h" #include "hw/watchdog/cmsdk-apb-watchdog.h" -#include "hw/misc/unimp.h" +#include "hw/misc/iotkit-sysctl.h" #include "hw/or-irq.h" #include "hw/core/split-irq.h" =20 @@ -97,6 +97,8 @@ typedef struct IoTKit { CMSDKAPBWatchdog nswatchdog; CMSDKAPBWatchdog swatchdog; =20 + IoTKitSysCtl sysctl; + MemoryRegion container; MemoryRegion alias1; MemoryRegion alias2; diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c index cb0ec456f39..5d59ed5489f 100644 --- a/hw/arm/iotkit.c +++ b/hw/arm/iotkit.c @@ -16,7 +16,6 @@ #include "hw/sysbus.h" #include "hw/registerfields.h" #include "hw/arm/iotkit.h" -#include "hw/misc/unimp.h" #include "hw/arm/arm.h" =20 /* Clock frequency in HZ of the 32KHz "slow clock" */ @@ -151,6 +150,8 @@ static void iotkit_init(Object *obj) sizeof(s->nswatchdog), TYPE_CMSDK_APB_WATCHDOG); sysbus_init_child_obj(obj, "swatchdog", &s->swatchdog, sizeof(s->swatchdog), TYPE_CMSDK_APB_WATCHDOG); + sysbus_init_child_obj(obj, "iotkit-sysctl", &s->sysctl, sizeof(s->sysc= tl), + TYPE_IOTKIT_SYSCTL); object_initialize_child(obj, "nmi-orgate", &s->nmi_orgate, sizeof(s->nmi_orgate), TYPE_OR_IRQ, &error_abort, NULL); @@ -516,13 +517,15 @@ static void iotkit_realize(DeviceState *dev, Error **= errp) qdev_get_gpio_in_named(dev_apb_ppc1, "cfg_sec_resp", 0)); =20 - /* Using create_unimplemented_device() maps the stub into the - * system address space rather than into our container, but the - * overall effect to the guest is the same. - */ - create_unimplemented_device("SYSINFO", 0x40020000, 0x1000); - - create_unimplemented_device("SYSCONTROL", 0x50021000, 0x1000); + object_property_set_bool(OBJECT(&s->sysctl), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + /* System information registers */ + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 0, 0x40020000); + /* System control registers */ + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysctl), 1, 0x50021000); =20 /* This OR gate wires together outputs from the secure watchdogs to NM= I */ object_property_set_int(OBJECT(&s->nmi_orgate), 2, "num-lines", &err); --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820371619521.7175397704083; Thu, 9 Aug 2018 06:12:51 -0700 (PDT) Received: from localhost ([::1]:50767 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkkE-0007zz-Dj for importer@patchew.org; Thu, 09 Aug 2018 09:12:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47268) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZT-0005zC-Ka for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZQ-0003P2-W9 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:43 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44194) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZD-00038J-TD; Thu, 09 Aug 2018 09:01:28 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZB-0003Hs-Hh; Thu, 09 Aug 2018 14:01:25 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:06 +0100 Message-Id: <20180809130115.28951-8-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 07/16] hw/misc/tz-msc: Model TrustZone Master Security 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 Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Implement a model of the TrustZone Master Securtiy Controller, as documented in the Arm CoreLink SIE-200 System IP for Embedded TRM (DDI0571G): https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g The MSC is intended to sit in front of a device which can be a bus master (eg a DMA controller) and programmably gate its transactions. This allows a bus-mastering device to be controlled by non-secure code but still restricted from making accesses to addresses which are secure-only. Signed-off-by: Peter Maydell --- hw/misc/Makefile.objs | 1 + include/hw/misc/tz-msc.h | 79 ++++++++ hw/misc/tz-msc.c | 308 ++++++++++++++++++++++++++++++++ MAINTAINERS | 2 + default-configs/arm-softmmu.mak | 1 + hw/misc/trace-events | 9 + 6 files changed, 400 insertions(+) create mode 100644 include/hw/misc/tz-msc.h create mode 100644 hw/misc/tz-msc.c diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index dbadb41d57a..d168f8ac304 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -63,6 +63,7 @@ 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_MSC) +=3D tz-msc.o obj-$(CONFIG_TZ_PPC) +=3D tz-ppc.o obj-$(CONFIG_IOTKIT_SECCTL) +=3D iotkit-secctl.o obj-$(CONFIG_IOTKIT_SYSCTL) +=3D iotkit-sysctl.o diff --git a/include/hw/misc/tz-msc.h b/include/hw/misc/tz-msc.h new file mode 100644 index 00000000000..116b96ae9b8 --- /dev/null +++ b/include/hw/misc/tz-msc.h @@ -0,0 +1,79 @@ +/* + * ARM TrustZone master security 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 master security controller (MSC). + * 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 MSC sits in front of a device which can be a bus master (such as + * a DMA controller) and allows secure software to configure it to either + * pass through or reject transactions made by that bus master. + * 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 MSC has no register interface -- it is configured purely by a + * collection of input signals from other hardware in the system. Typically + * they are either hardwired or exposed in an ad-hoc register interface by + * the SoC that uses the MSC. + * + * We don't currently implement the irq_enable GPIO input, because on + * the MPS2 FPGA images it is always tied high, which is awkward to + * implement in QEMU. + * + * QEMU interface: + * + Named GPIO input "cfg_nonsec": set to 1 if the bus master should be + * treated as nonsecure, or 0 for secure + * + Named GPIO input "cfg_sec_resp": set to 1 if a rejected transaction s= hould + * result in a transaction error, or 0 for the transaction to RAZ/WI + * + Named GPIO input "irq_clear": set to 1 to clear a pending interrupt + * + Named GPIO output "irq": set for a transaction-failed interrupt + * + Property "downstream": MemoryRegion defining where bus master transac= tions + * are made if they are not blocked + * + Property "idau": an object implementing IDAUInterface, which defines = which + * addresses should be treated as secure and which as non-secure. + * This need not be the same IDAU as the one used by the CPU. + * + sysbus MMIO region 0: MemoryRegion defining the upstream end of the M= SC; + * this should be passed to the bus master device as the region it should + * make memory transactions to + */ + +#ifndef TZ_MSC_H +#define TZ_MSC_H + +#include "hw/sysbus.h" +#include "target/arm/idau.h" + +#define TYPE_TZ_MSC "tz-msc" +#define TZ_MSC(obj) OBJECT_CHECK(TZMSC, (obj), TYPE_TZ_MSC) + +typedef struct TZMSC { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + + /* State: these just track the values of our input signals */ + bool cfg_nonsec; + bool cfg_sec_resp; + bool irq_clear; + /* State: are we asserting irq ? */ + bool irq_status; + + qemu_irq irq; + MemoryRegion *downstream; + AddressSpace downstream_as; + MemoryRegion upstream; + IDAUInterface *idau; +} TZMSC; + +#endif diff --git a/hw/misc/tz-msc.c b/hw/misc/tz-msc.c new file mode 100644 index 00000000000..9e352044ea5 --- /dev/null +++ b/hw/misc/tz-msc.c @@ -0,0 +1,308 @@ +/* + * ARM TrustZone master security 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-msc.h" + +static void tz_msc_update_irq(TZMSC *s) +{ + bool level =3D s->irq_status; + + trace_tz_msc_update_irq(level); + qemu_set_irq(s->irq, level); +} + +static void tz_msc_cfg_nonsec(void *opaque, int n, int level) +{ + TZMSC *s =3D TZ_MSC(opaque); + + trace_tz_msc_cfg_nonsec(level); + s->cfg_nonsec =3D level; +} + +static void tz_msc_cfg_sec_resp(void *opaque, int n, int level) +{ + TZMSC *s =3D TZ_MSC(opaque); + + trace_tz_msc_cfg_sec_resp(level); + s->cfg_sec_resp =3D level; +} + +static void tz_msc_irq_clear(void *opaque, int n, int level) +{ + TZMSC *s =3D TZ_MSC(opaque); + + trace_tz_msc_irq_clear(level); + + s->irq_clear =3D level; + if (level) { + s->irq_status =3D false; + tz_msc_update_irq(s); + } +} + +/* The MSC may either block a transaction by aborting it, block a + * transaction by making it RAZ/WI, allow it through with + * MemTxAttrs indicating a secure transaction, or allow it with + * MemTxAttrs indicating a non-secure transaction. + */ +typedef enum MSCAction { + MSCBlockAbort, + MSCBlockRAZWI, + MSCAllowSecure, + MSCAllowNonSecure, +} MSCAction; + +static MSCAction tz_msc_check(TZMSC *s, hwaddr addr) +{ + /* + * Check whether to allow an access from the bus master, returning + * an MSCAction indicating the required behaviour. If the transaction + * is blocked, the caller must check cfg_sec_resp to determine + * whether to abort or RAZ/WI the transaction. + */ + IDAUInterfaceClass *iic =3D IDAU_INTERFACE_GET_CLASS(s->idau); + IDAUInterface *ii =3D IDAU_INTERFACE(s->idau); + bool idau_exempt =3D false, idau_ns =3D true, idau_nsc =3D true; + int idau_region =3D IREGION_NOTVALID; + + iic->check(ii, addr, &idau_region, &idau_exempt, &idau_ns, &idau_nsc); + + if (idau_exempt) { + /* + * Uncheck region -- OK, transaction type depends on + * whether bus master is configured as Secure or NonSecure + */ + return s->cfg_nonsec ? MSCAllowNonSecure : MSCAllowSecure; + } + + if (idau_ns) { + /* NonSecure region -- always forward as NS transaction */ + return MSCAllowNonSecure; + } + + if (!s->cfg_nonsec) { + /* Access to Secure region by Secure bus master: OK */ + return MSCAllowSecure; + } + + /* Attempted access to Secure region by NS bus master: block */ + trace_tz_msc_access_blocked(addr); + if (!s->cfg_sec_resp) { + return MSCBlockRAZWI; + } + + /* + * The TRM isn't clear on behaviour if irq_clear is high when a + * transaction is blocked. We assume that the MSC behaves like the + * PPC, where holding irq_clear high suppresses the interrupt. + */ + if (!s->irq_clear) { + s->irq_status =3D true; + tz_msc_update_irq(s); + } + return MSCBlockAbort; +} + +static MemTxResult tz_msc_read(void *opaque, hwaddr addr, uint64_t *pdata, + unsigned size, MemTxAttrs attrs) +{ + TZMSC *s =3D opaque; + AddressSpace *as =3D &s->downstream_as; + uint64_t data; + MemTxResult res; + + switch (tz_msc_check(s, addr)) { + case MSCBlockAbort: + return MEMTX_ERROR; + case MSCBlockRAZWI: + *pdata =3D 0; + return MEMTX_OK; + case MSCAllowSecure: + attrs.secure =3D 1; + attrs.unspecified =3D 0; + break; + case MSCAllowNonSecure: + attrs.secure =3D 0; + attrs.unspecified =3D 0; + break; + } + + switch (size) { + case 1: + data =3D address_space_ldub(as, addr, attrs, &res); + break; + case 2: + data =3D address_space_lduw_le(as, addr, attrs, &res); + break; + case 4: + data =3D address_space_ldl_le(as, addr, attrs, &res); + break; + case 8: + data =3D address_space_ldq_le(as, addr, attrs, &res); + break; + default: + g_assert_not_reached(); + } + *pdata =3D data; + return res; +} + +static MemTxResult tz_msc_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size, MemTxAttrs attrs) +{ + TZMSC *s =3D opaque; + AddressSpace *as =3D &s->downstream_as; + MemTxResult res; + + switch (tz_msc_check(s, addr)) { + case MSCBlockAbort: + return MEMTX_ERROR; + case MSCBlockRAZWI: + return MEMTX_OK; + case MSCAllowSecure: + attrs.secure =3D 1; + attrs.unspecified =3D 0; + break; + case MSCAllowNonSecure: + attrs.secure =3D 0; + attrs.unspecified =3D 0; + break; + } + + switch (size) { + case 1: + address_space_stb(as, addr, val, attrs, &res); + break; + case 2: + address_space_stw_le(as, addr, val, attrs, &res); + break; + case 4: + address_space_stl_le(as, addr, val, attrs, &res); + break; + case 8: + address_space_stq_le(as, addr, val, attrs, &res); + break; + default: + g_assert_not_reached(); + } + return res; +} + +static const MemoryRegionOps tz_msc_ops =3D { + .read_with_attrs =3D tz_msc_read, + .write_with_attrs =3D tz_msc_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, +}; + +static void tz_msc_reset(DeviceState *dev) +{ + TZMSC *s =3D TZ_MSC(dev); + + trace_tz_msc_reset(); + s->cfg_sec_resp =3D false; + s->cfg_nonsec =3D false; + s->irq_clear =3D 0; + s->irq_status =3D 0; +} + +static void tz_msc_init(Object *obj) +{ + DeviceState *dev =3D DEVICE(obj); + TZMSC *s =3D TZ_MSC(obj); + + qdev_init_gpio_in_named(dev, tz_msc_cfg_nonsec, "cfg_nonsec", 1); + qdev_init_gpio_in_named(dev, tz_msc_cfg_sec_resp, "cfg_sec_resp", 1); + qdev_init_gpio_in_named(dev, tz_msc_irq_clear, "irq_clear", 1); + qdev_init_gpio_out_named(dev, &s->irq, "irq", 1); +} + +static void tz_msc_realize(DeviceState *dev, Error **errp) +{ + Object *obj =3D OBJECT(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + TZMSC *s =3D TZ_MSC(dev); + const char *name =3D "tz-msc-downstream"; + 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, "MSC 'downstream' link not set"); + return; + } + if (!s->idau) { + error_setg(errp, "MSC 'idau' link not set"); + return; + } + + size =3D memory_region_size(s->downstream); + address_space_init(&s->downstream_as, s->downstream, name); + memory_region_init_io(&s->upstream, obj, &tz_msc_ops, s, name, size); + sysbus_init_mmio(sbd, &s->upstream); +} + +static const VMStateDescription tz_msc_vmstate =3D { + .name =3D "tz-msc", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) { + VMSTATE_BOOL(cfg_nonsec, TZMSC), + VMSTATE_BOOL(cfg_sec_resp, TZMSC), + VMSTATE_BOOL(irq_clear, TZMSC), + VMSTATE_BOOL(irq_status, TZMSC), + VMSTATE_END_OF_LIST() + } +}; + +static Property tz_msc_properties[] =3D { + DEFINE_PROP_LINK("downstream", TZMSC, downstream, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_LINK("idau", TZMSC, idau, + TYPE_IDAU_INTERFACE, IDAUInterface *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void tz_msc_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + + dc->realize =3D tz_msc_realize; + dc->vmsd =3D &tz_msc_vmstate; + dc->reset =3D tz_msc_reset; + dc->props =3D tz_msc_properties; +} + +static const TypeInfo tz_msc_info =3D { + .name =3D TYPE_TZ_MSC, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(TZMSC), + .instance_init =3D tz_msc_init, + .class_init =3D tz_msc_class_init, +}; + +static void tz_msc_register_types(void) +{ + type_register_static(&tz_msc_info); +} + +type_init(tz_msc_register_types); diff --git a/MAINTAINERS b/MAINTAINERS index 96fe011e952..5d1a3645dd4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -463,6 +463,8 @@ 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 +F: hw/misc/tz-msc.c +F: include/hw/misc/tz-msc.h =20 ARM cores M: Peter Maydell diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.= mak index da59b820a4f..1f2ac3b1767 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -111,6 +111,7 @@ CONFIG_MPS2_FPGAIO=3Dy CONFIG_MPS2_SCC=3Dy =20 CONFIG_TZ_MPC=3Dy +CONFIG_TZ_MSC=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 83ab58c30f5..f9be1b822e7 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -92,6 +92,15 @@ tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, u= nsigned size, bool secur 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-msc.c +tz_msc_reset(void) "TZ MSC: reset" +tz_msc_cfg_nonsec(int level) "TZ MSC: cfg_nonsec =3D %d" +tz_msc_cfg_sec_resp(int level) "TZ MSC: cfg_sec_resp =3D %d" +tz_msc_irq_enable(int level) "TZ MSC: int_enable =3D %d" +tz_msc_irq_clear(int level) "TZ MSC: int_clear =3D %d" +tz_msc_update_irq(int level) "TZ MSC: setting irq line to %d" +tz_msc_access_blocked(uint64_t offset) "TZ MSC: offset 0x%" PRIx64 " acces= s blocked" + # 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 Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153382046654343.73208148565436; Thu, 9 Aug 2018 06:14:26 -0700 (PDT) Received: from localhost ([::1]:50775 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkll-0001Ga-8B for importer@patchew.org; Thu, 09 Aug 2018 09:14:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47364) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZX-00063T-Ri for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZR-0003Ps-P6 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:47 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44194) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZF-00038J-1Y; Thu, 09 Aug 2018 09:01:29 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZC-0003IK-GG; Thu, 09 Aug 2018 14:01:26 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:07 +0100 Message-Id: <20180809130115.28951-9-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 08/16] hw/misc/iotkit-secctl: Wire up registers for controlling MSCs 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The IoTKit does not have any Master Security Contollers itself, but it does provide registers in the secure privilege control block which allow control of MSCs in the external system. Add support for these registers. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/misc/iotkit-secctl.h | 14 +++++++ hw/misc/iotkit-secctl.c | 73 +++++++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secct= l.h index 082c14c925e..1a193b306f1 100644 --- a/include/hw/misc/iotkit-secctl.h +++ b/include/hw/misc/iotkit-secctl.h @@ -19,6 +19,7 @@ * + named GPIO output "sec_resp_cfg" indicating whether blocked accesses * should RAZ/WI or bus error * + named GPIO output "nsc_cfg" whose value tracks the NSCCFG register v= alue + * + named GPIO output "msc_irq" for the combined IRQ line from the MSCs * Controlling the 2 APB PPCs in the IoTKit: * + named GPIO outputs apb_ppc0_nonsec[0..2] and apb_ppc1_nonsec * + named GPIO outputs apb_ppc0_ap[0..2] and apb_ppc1_ap @@ -44,6 +45,11 @@ * Controlling each of the 16 expansion MPCs which a system using the IoTK= it * might provide: * + named GPIO inputs mpcexp_status[0..15] + * Controlling each of the 16 expansion MSCs which a system using the IoTK= it + * might provide: + * + named GPIO inputs mscexp_status[0..15] + * + named GPIO outputs mscexp_clear[0..15] + * + named GPIO outputs mscexp_ns[0..15] */ =20 #ifndef IOTKIT_SECCTL_H @@ -62,6 +68,7 @@ #define IOTS_NUM_AHB_EXP_PPC 4 #define IOTS_NUM_EXP_MPC 16 #define IOTS_NUM_MPC 1 +#define IOTS_NUM_EXP_MSC 16 =20 typedef struct IoTKitSecCtl IoTKitSecCtl; =20 @@ -103,6 +110,13 @@ struct IoTKitSecCtl { uint32_t brginten; uint32_t mpcintstatus; =20 + uint32_t secmscintstat; + uint32_t secmscinten; + uint32_t nsmscexp; + qemu_irq mscexp_clear[IOTS_NUM_EXP_MSC]; + qemu_irq mscexp_ns[IOTS_NUM_EXP_MSC]; + qemu_irq msc_irq; + IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC]; IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC]; IoTKitSecCtlPPC ahbexp[IOTS_NUM_APB_EXP_PPC]; diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c index de4fd8e36d2..2222b3e147d 100644 --- a/hw/misc/iotkit-secctl.c +++ b/hw/misc/iotkit-secctl.c @@ -190,12 +190,13 @@ static MemTxResult iotkit_secctl_s_read(void *opaque,= hwaddr addr, r =3D s->apbexp[offset_to_ppc_idx(offset)].sp; break; case A_SECMSCINTSTAT: + r =3D s->secmscintstat; + break; case A_SECMSCINTEN: + r =3D s->secmscinten; + break; case A_NSMSCEXP: - qemu_log_mask(LOG_UNIMP, - "IoTKit SecCtl S block read: " - "unimplemented offset 0x%x\n", offset); - r =3D 0; + r =3D s->nsmscexp; break; case A_PID4: case A_PID5: @@ -291,6 +292,23 @@ static void iotkit_secctl_ppc_update_irq_enable(IoTKit= SecCtlPPC *ppc) qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1)= ); } =20 +static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t = value) +{ + int i; + + for (i =3D 0; i < IOTS_NUM_EXP_MSC; i++) { + qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1)); + } +} + +static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s) +{ + /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_= EN */ + bool level =3D s->secmscintstat & s->secmscinten; + + qemu_set_irq(s->msc_irq, level); +} + static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr, uint64_t value, unsigned size, MemTxAttrs attrs) @@ -370,10 +388,15 @@ static MemTxResult iotkit_secctl_s_write(void *opaque= , hwaddr addr, iotkit_secctl_ppc_sp_write(ppc, value); break; case A_SECMSCINTCLR: + iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value); + break; case A_SECMSCINTEN: - qemu_log_mask(LOG_UNIMP, - "IoTKit SecCtl S block write: " - "unimplemented offset 0x%x\n", offset); + s->secmscinten =3D value; + iotkit_secctl_update_msc_irq(s); + break; + case A_NSMSCEXP: + s->nsmscexp =3D value; + iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value); break; case A_SECMPCINTSTATUS: case A_SECPPCINTSTAT: @@ -381,7 +404,6 @@ static MemTxResult iotkit_secctl_s_write(void *opaque, = hwaddr addr, case A_BRGINTSTAT: case A_AHBNSPPC0: case A_AHBSPPPC0: - case A_NSMSCEXP: case A_PID4: case A_PID5: case A_PID6: @@ -588,6 +610,14 @@ static void iotkit_secctl_mpcexp_status(void *opaque, = int n, int level) s->mpcintstatus =3D deposit32(s->mpcintstatus, n + 16, 1, !!level); } =20 +static void iotkit_secctl_mscexp_status(void *opaque, int n, int level) +{ + IoTKitSecCtl *s =3D IOTKIT_SECCTL(opaque); + + s->secmscintstat =3D deposit32(s->secmscintstat, n + 16, 1, !!level); + iotkit_secctl_update_msc_irq(s); +} + static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level) { IoTKitSecCtlPPC *ppc =3D opaque; @@ -660,6 +690,14 @@ static void iotkit_secctl_init(Object *obj) qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status, "mpcexp_status", IOTS_NUM_EXP_MPC); =20 + qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status, + "mscexp_status", IOTS_NUM_EXP_MSC); + qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear", + IOTS_NUM_EXP_MSC); + qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns", + IOTS_NUM_EXP_MSC); + qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1); + 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, @@ -690,6 +728,24 @@ static const VMStateDescription iotkit_secctl_mpcintst= atus_vmstate =3D { } }; =20 +static bool needed_always(void *opaque) +{ + return true; +} + +static const VMStateDescription iotkit_secctl_msc_vmstate =3D { + .name =3D "iotkit-secctl/msc", + .version_id =3D 1, + .minimum_version_id =3D 1, + .needed =3D needed_always, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(secmscintstat, IoTKitSecCtl), + VMSTATE_UINT32(secmscinten, IoTKitSecCtl), + VMSTATE_UINT32(nsmscexp, IoTKitSecCtl), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription iotkit_secctl_vmstate =3D { .name =3D "iotkit-secctl", .version_id =3D 1, @@ -710,6 +766,7 @@ static const VMStateDescription iotkit_secctl_vmstate = =3D { }, .subsections =3D (const VMStateDescription*[]) { &iotkit_secctl_mpcintstatus_vmstate, + &iotkit_secctl_msc_vmstate, NULL }, }; --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533819914371829.2135261091233; Thu, 9 Aug 2018 06:05:14 -0700 (PDT) Received: from localhost ([::1]:50714 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkcr-0008R0-4v for importer@patchew.org; Thu, 09 Aug 2018 09:05:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47273) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZU-0005zF-A1 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZO-0003NN-Kd for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:44 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44214) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZE-0003Gd-I9; Thu, 09 Aug 2018 09:01:28 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZD-0003Ip-Cd; Thu, 09 Aug 2018 14:01:27 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:08 +0100 Message-Id: <20180809130115.28951-10-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 09/16] hw/arm/iotkit: Wire up the lines for MSCs 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The IoTKit doesn't have any MSCs itself but it does need some wiring to connect the external signals from MSCs in the outer board model up to the registers and the NVIC IRQ line. We also need to expose a MemoryRegion corresponding to the AHB bus, so that MSCs in the outer board model can use that as their downstream port. (In the FPGA this is the "AHB Slave Expansion" ports shown in the block diagram in the AN505 documentation.) Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/arm/iotkit.h | 8 ++++++++ hw/arm/iotkit.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h index 1ffa31d521b..5bb66b10468 100644 --- a/include/hw/arm/iotkit.h +++ b/include/hw/arm/iotkit.h @@ -28,6 +28,9 @@ * + QOM property "EXP_NUMIRQ" sets the number of expansion interrupts * + Named GPIO inputs "EXP_IRQ" 0..n are the expansion interrupts, which * are wired to the NVIC lines 32 .. n+32 + * + sysbus MMIO region 0 is the "AHB Slave Expansion" which allows + * bus master devices in the board model to make transactions into + * all the devices and memory areas in the IoTKit * Controlling up to 4 AHB expansion PPBs which a system using the IoTKit * might provide: * + named GPIO outputs apb_ppcexp{0,1,2,3}_nonsec[0..15] @@ -45,6 +48,11 @@ * Controlling each of the 16 expansion MPCs which a system using the IoTK= it * might provide: * + named GPIO inputs mpcexp_status[0..15] + * Controlling each of the 16 expansion MSCs which a system using the IoTK= it + * might provide: + * + named GPIO inputs mscexp_status[0..15] + * + named GPIO outputs mscexp_clear[0..15] + * + named GPIO outputs mscexp_ns[0..15] */ =20 #ifndef IOTKIT_H diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c index 5d59ed5489f..8ae2a052517 100644 --- a/hw/arm/iotkit.c +++ b/hw/arm/iotkit.c @@ -660,6 +660,21 @@ static void iotkit_realize(DeviceState *dev, Error **e= rrp) =20 iotkit_forward_sec_resp_cfg(s); =20 + /* Forward the MSC related signals */ + qdev_pass_gpios(dev_secctl, dev, "mscexp_status"); + qdev_pass_gpios(dev_secctl, dev, "mscexp_clear"); + qdev_pass_gpios(dev_secctl, dev, "mscexp_ns"); + qdev_connect_gpio_out_named(dev_secctl, "msc_irq", 0, + qdev_get_gpio_in(DEVICE(&s->armv7m), 11)); + + /* + * Expose our container region to the board model; this corresponds + * to the AHB Slave Expansion ports which allow bus master devices + * (eg DMA controllers) in the board model to make transactions into + * devices in the IoTKit. + */ + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container); + system_clock_scale =3D NANOSECONDS_PER_SECOND / s->mainclk_frq; } =20 --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 15338198672241001.4017505966287; Thu, 9 Aug 2018 06:04:27 -0700 (PDT) Received: from localhost ([::1]:50707 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkbw-0007hz-EH for importer@patchew.org; Thu, 09 Aug 2018 09:04:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47171) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZP-0005wL-ML for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZO-0003Na-LH for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:39 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44194) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZG-00038J-0s; Thu, 09 Aug 2018 09:01:30 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZE-0003J5-DM; Thu, 09 Aug 2018 14:01:28 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:09 +0100 Message-Id: <20180809130115.28951-11-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 10/16] hw/dma/pl080: Allow use as embedded-struct device 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Create a new include file for the pl081's device struct, type macros, etc, so that it can be instantiated using the "embedded struct" coding style. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/dma/pl080.h | 62 ++++++++++++++++++++++++++++++++++++++++++ hw/dma/pl080.c | 34 ++--------------------- MAINTAINERS | 1 + 3 files changed, 65 insertions(+), 32 deletions(-) create mode 100644 include/hw/dma/pl080.h diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h new file mode 100644 index 00000000000..7deb46c8578 --- /dev/null +++ b/include/hw/dma/pl080.h @@ -0,0 +1,62 @@ +/* + * ARM PrimeCell PL080/PL081 DMA controller + * + * Copyright (c) 2006 CodeSourcery. + * Copyright (c) 2018 Linaro Limited + * Written by Paul Brook, 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 Arm PrimeCell PL080/PL081 DMA controller: + * The PL080 TRM is: + * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0196g/DDI0196.pdf + * and the PL081 TRM is: + * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf + * + * QEMU interface: + * + sysbus IRQ: DMACINTR combined interrupt line + * + sysbus MMIO region 0: MemoryRegion for the device's registers + */ + +#ifndef HW_DMA_PL080_H +#define HW_DMA_PL080_H + +#include "hw/sysbus.h" + +#define PL080_MAX_CHANNELS 8 + +typedef struct { + uint32_t src; + uint32_t dest; + uint32_t lli; + uint32_t ctrl; + uint32_t conf; +} pl080_channel; + +#define TYPE_PL080 "pl080" +#define TYPE_PL081 "pl081" +#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080) + +typedef struct PL080State { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint8_t tc_int; + uint8_t tc_mask; + uint8_t err_int; + uint8_t err_mask; + uint32_t conf; + uint32_t sync; + uint32_t req_single; + uint32_t req_burst; + pl080_channel chan[PL080_MAX_CHANNELS]; + int nchannels; + /* Flag to avoid recursive DMA invocations. */ + int running; + qemu_irq irq; +} PL080State; + +#endif diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 7724c93b8f2..0f79c2d8a6c 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -11,8 +11,8 @@ #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "qemu/log.h" +#include "hw/dma/pl080.h" =20 -#define PL080_MAX_CHANNELS 8 #define PL080_CONF_E 0x1 #define PL080_CONF_M1 0x2 #define PL080_CONF_M2 0x4 @@ -30,36 +30,6 @@ #define PL080_CCTRL_D 0x02000000 #define PL080_CCTRL_S 0x01000000 =20 -typedef struct { - uint32_t src; - uint32_t dest; - uint32_t lli; - uint32_t ctrl; - uint32_t conf; -} pl080_channel; - -#define TYPE_PL080 "pl080" -#define PL080(obj) OBJECT_CHECK(PL080State, (obj), TYPE_PL080) - -typedef struct PL080State { - SysBusDevice parent_obj; - - MemoryRegion iomem; - uint8_t tc_int; - uint8_t tc_mask; - uint8_t err_int; - uint8_t err_mask; - uint32_t conf; - uint32_t sync; - uint32_t req_single; - uint32_t req_burst; - pl080_channel chan[PL080_MAX_CHANNELS]; - int nchannels; - /* Flag to avoid recursive DMA invocations. */ - int running; - qemu_irq irq; -} PL080State; - static const VMStateDescription vmstate_pl080_channel =3D { .name =3D "pl080_channel", .version_id =3D 1, @@ -408,7 +378,7 @@ static const TypeInfo pl080_info =3D { }; =20 static const TypeInfo pl081_info =3D { - .name =3D "pl081", + .name =3D TYPE_PL081, .parent =3D TYPE_PL080, .instance_init =3D pl081_init, }; diff --git a/MAINTAINERS b/MAINTAINERS index 5d1a3645dd4..92ccca716c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -444,6 +444,7 @@ F: hw/char/pl011.c F: include/hw/char/pl011.h F: hw/display/pl110* F: hw/dma/pl080.c +F: include/hw/dma/pl080.h F: hw/dma/pl330.c F: hw/gpio/pl061.c F: hw/input/pl050.c --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820418375780.8372953518249; Thu, 9 Aug 2018 06:13:38 -0700 (PDT) Received: from localhost ([::1]:50772 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkkz-0000Xl-3Z for importer@patchew.org; Thu, 09 Aug 2018 09:13:37 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47434) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZe-000680-F9 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZU-0003S8-OB for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:54 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44220) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZG-0003Hp-CR; Thu, 09 Aug 2018 09:01:30 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZF-0003Jc-Ba; Thu, 09 Aug 2018 14:01:29 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:10 +0100 Message-Id: <20180809130115.28951-12-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 11/16] hw/dma/pl080: Support all three 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 Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The PL080 and PL081 have three outgoing interrupt lines: * DMACINTERR signals DMA errors * DMACINTTC is the DMA count interrupt * DMACINTR is a combined interrupt, the logical OR of the other two We currently only implement DMACINTR, because that's all the realview and versatile boards needed, but the instances of the PL081 in the MPS2 firmware images use all three interrupt lines. Implement the missing DMACINTERR and DMACINTTC. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/dma/pl080.h | 6 +++++- hw/dma/pl080.c | 13 ++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h index 7deb46c8578..7c6a4184833 100644 --- a/include/hw/dma/pl080.h +++ b/include/hw/dma/pl080.h @@ -17,7 +17,9 @@ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0218e/DDI0218.pdf * * QEMU interface: - * + sysbus IRQ: DMACINTR combined interrupt line + * + sysbus IRQ 0: DMACINTR combined interrupt line + * + sysbus IRQ 1: DMACINTERR error interrupt request + * + sysbus IRQ 2: DMACINTTC count interrupt request * + sysbus MMIO region 0: MemoryRegion for the device's registers */ =20 @@ -57,6 +59,8 @@ typedef struct PL080State { /* Flag to avoid recursive DMA invocations. */ int running; qemu_irq irq; + qemu_irq interr; + qemu_irq inttc; } PL080State; =20 #endif diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 0f79c2d8a6c..301030dd118 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -75,11 +75,12 @@ static const unsigned char pl081_id[] =3D =20 static void pl080_update(PL080State *s) { - if ((s->tc_int & s->tc_mask) - || (s->err_int & s->err_mask)) - qemu_irq_raise(s->irq); - else - qemu_irq_lower(s->irq); + bool tclevel =3D (s->tc_int & s->tc_mask); + bool errlevel =3D (s->err_int & s->err_mask); + + qemu_set_irq(s->interr, errlevel); + qemu_set_irq(s->inttc, tclevel); + qemu_set_irq(s->irq, errlevel || tclevel); } =20 static void pl080_run(PL080State *s) @@ -352,6 +353,8 @@ static void pl080_init(Object *obj) memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x= 1000); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); + sysbus_init_irq(sbd, &s->interr); + sysbus_init_irq(sbd, &s->inttc); s->nchannels =3D 8; } =20 --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820218618166.7523352204879; Thu, 9 Aug 2018 06:10:18 -0700 (PDT) Received: from localhost ([::1]:50750 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkhY-0004rq-Dx for importer@patchew.org; Thu, 09 Aug 2018 09:10:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47406) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZa-00064g-14 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZU-0003S7-OK for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:50 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44226) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZI-0003IY-AF; Thu, 09 Aug 2018 09:01:32 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZH-0003K6-3f; Thu, 09 Aug 2018 14:01:31 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:11 +0100 Message-Id: <20180809130115.28951-13-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 12/16] hw/dma/pl080: Don't use CPU address space for DMA accesses 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Currently our PL080/PL081 model uses a combination of the CPU's address space (via cpu_physical_memory_{read,write}()) and the system address space for performing DMA accesses. For the PL081s in the MPS FPGA images, their DMA accesses must go via Master Security Controllers. Switch the PL080/PL081 model to take a MemoryRegion property which defines its downstream for making DMA accesses. Since the PL08x are only used in two board models, we make provision of the 'downstream' link mandatory and convert both users at once, rather than having it be optional with a default to the system address space. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- include/hw/dma/pl080.h | 5 +++++ hw/arm/realview.c | 8 +++++++- hw/arm/versatilepb.c | 9 ++++++++- hw/dma/pl080.c | 35 +++++++++++++++++++++++++++++------ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/include/hw/dma/pl080.h b/include/hw/dma/pl080.h index 7c6a4184833..9d4b3df143f 100644 --- a/include/hw/dma/pl080.h +++ b/include/hw/dma/pl080.h @@ -21,6 +21,8 @@ * + sysbus IRQ 1: DMACINTERR error interrupt request * + sysbus IRQ 2: DMACINTTC count interrupt request * + sysbus MMIO region 0: MemoryRegion for the device's registers + * + QOM property "downstream": MemoryRegion defining where DMA + * bus master transactions are made */ =20 #ifndef HW_DMA_PL080_H @@ -61,6 +63,9 @@ typedef struct PL080State { qemu_irq irq; qemu_irq interr; qemu_irq inttc; + + MemoryRegion *downstream; + AddressSpace downstream_as; } PL080State; =20 #endif diff --git a/hw/arm/realview.c b/hw/arm/realview.c index cd585d94694..ab8c14fde38 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -201,7 +201,13 @@ static void realview_init(MachineState *machine, pl011_create(0x1000c000, pic[15], serial_hd(3)); =20 /* DMA controller is optional, apparently. */ - sysbus_create_simple("pl081", 0x10030000, pic[24]); + dev =3D qdev_create(NULL, "pl081"); + object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream", + &error_fatal); + qdev_init_nofail(dev); + busdev =3D SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, 0x10030000); + sysbus_connect_irq(busdev, 0, pic[24]); =20 sysbus_create_simple("sp804", 0x10011000, pic[4]); sysbus_create_simple("sp804", 0x10012000, pic[5]); diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index a5a06b6d408..8b748570596 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -287,7 +287,14 @@ static void versatile_init(MachineState *machine, int = board_id) pl011_create(0x101f3000, pic[14], serial_hd(2)); pl011_create(0x10009000, sic[6], serial_hd(3)); =20 - sysbus_create_simple("pl080", 0x10130000, pic[17]); + dev =3D qdev_create(NULL, "pl080"); + object_property_set_link(OBJECT(dev), OBJECT(sysmem), "downstream", + &error_fatal); + qdev_init_nofail(dev); + busdev =3D SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, 0x10130000); + sysbus_connect_irq(busdev, 0, pic[17]); + sysbus_create_simple("sp804", 0x101e2000, pic[4]); sysbus_create_simple("sp804", 0x101e3000, pic[5]); =20 diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 301030dd118..8f9f3e08d9a 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -12,6 +12,7 @@ #include "exec/address-spaces.h" #include "qemu/log.h" #include "hw/dma/pl080.h" +#include "qapi/error.h" =20 #define PL080_CONF_E 0x1 #define PL080_CONF_M1 0x2 @@ -161,14 +162,16 @@ again: swidth =3D 1 << ((ch->ctrl >> 18) & 7); dwidth =3D 1 << ((ch->ctrl >> 21) & 7); for (n =3D 0; n < dwidth; n+=3D swidth) { - cpu_physical_memory_read(ch->src, buff + n, swidth); + address_space_read(&s->downstream_as, ch->src, + MEMTXATTRS_UNSPECIFIED, buff + n, swidt= h); if (ch->ctrl & PL080_CCTRL_SI) ch->src +=3D swidth; } xsize =3D (dwidth < swidth) ? swidth : dwidth; /* ??? This may pad the value incorrectly for dwidth < 32. */ for (n =3D 0; n < xsize; n +=3D dwidth) { - cpu_physical_memory_write(ch->dest + n, buff + n, dwidth); + address_space_write(&s->downstream_as, ch->dest + n, + MEMTXATTRS_UNSPECIFIED, buff + n, dwid= th); if (ch->ctrl & PL080_CCTRL_DI) ch->dest +=3D swidth; } @@ -178,19 +181,19 @@ again: if (size =3D=3D 0) { /* Transfer complete. */ if (ch->lli) { - ch->src =3D address_space_ldl_le(&address_space_memory, + ch->src =3D address_space_ldl_le(&s->downstream_as, ch->lli, MEMTXATTRS_UNSPECIFIED, NULL); - ch->dest =3D address_space_ldl_le(&address_space_memor= y, + ch->dest =3D address_space_ldl_le(&s->downstream_as, ch->lli + 4, MEMTXATTRS_UNSPECIFIED, NULL); - ch->ctrl =3D address_space_ldl_le(&address_space_memor= y, + ch->ctrl =3D address_space_ldl_le(&s->downstream_as, ch->lli + 12, MEMTXATTRS_UNSPECIFIED, NULL); - ch->lli =3D address_space_ldl_le(&address_space_memory, + ch->lli =3D address_space_ldl_le(&s->downstream_as, ch->lli + 8, MEMTXATTRS_UNSPECIFIED, NULL); @@ -358,6 +361,18 @@ static void pl080_init(Object *obj) s->nchannels =3D 8; } =20 +static void pl080_realize(DeviceState *dev, Error **errp) +{ + PL080State *s =3D PL080(dev); + + if (!s->downstream) { + error_setg(errp, "PL080 'downstream' link not set"); + return; + } + + address_space_init(&s->downstream_as, s->downstream, "pl080-downstream= "); +} + static void pl081_init(Object *obj) { PL080State *s =3D PL080(obj); @@ -365,11 +380,19 @@ static void pl081_init(Object *obj) s->nchannels =3D 2; } =20 +static Property pl080_properties[] =3D { + DEFINE_PROP_LINK("downstream", PL080State, downstream, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), +}; + static void pl080_class_init(ObjectClass *oc, void *data) { DeviceClass *dc =3D DEVICE_CLASS(oc); =20 dc->vmsd =3D &vmstate_pl080; + dc->realize =3D pl080_realize; + dc->props =3D pl080_properties; } =20 static const TypeInfo pl080_info =3D { --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820144128111.11977003683558; Thu, 9 Aug 2018 06:09:04 -0700 (PDT) Received: from localhost ([::1]:50744 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkgZ-000406-01 for importer@patchew.org; Thu, 09 Aug 2018 09:09:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47305) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZV-000615-Kk for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZU-0003SK-Ng for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:45 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44230) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZL-0003KI-0m; Thu, 09 Aug 2018 09:01:35 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZI-0003Ko-1x; Thu, 09 Aug 2018 14:01:32 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:12 +0100 Message-Id: <20180809130115.28951-14-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 13/16] hw/dma/pl080: Provide device reset function 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The PL080/PL081 model is missing a reset function; implement it. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/dma/pl080.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 8f9f3e08d9a..a7aacad74f0 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -348,6 +348,30 @@ static const MemoryRegionOps pl080_ops =3D { .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 +static void pl080_reset(DeviceState *dev) +{ + PL080State *s =3D PL080(dev); + int i; + + s->tc_int =3D 0; + s->tc_mask =3D 0; + s->err_int =3D 0; + s->err_mask =3D 0; + s->conf =3D 0; + s->sync =3D 0; + s->req_single =3D 0; + s->req_burst =3D 0; + s->running =3D 0; + + for (i =3D 0; i < s->nchannels; i++) { + s->chan[i].src =3D 0; + s->chan[i].dest =3D 0; + s->chan[i].lli =3D 0; + s->chan[i].ctrl =3D 0; + s->chan[i].conf =3D 0; + } +} + static void pl080_init(Object *obj) { SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); @@ -393,6 +417,7 @@ static void pl080_class_init(ObjectClass *oc, void *dat= a) dc->vmsd =3D &vmstate_pl080; dc->realize =3D pl080_realize; dc->props =3D pl080_properties; + dc->reset =3D pl080_reset; } =20 static const TypeInfo pl080_info =3D { --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 153382060781327.08491518179335; Thu, 9 Aug 2018 06:16:47 -0700 (PDT) Received: from localhost ([::1]:50793 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnko2-0003tG-N1 for importer@patchew.org; Thu, 09 Aug 2018 09:16:46 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47360) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZX-00063J-KO for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZW-0003WH-Im for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:47 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44230) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZK-0003KI-2N; Thu, 09 Aug 2018 09:01:34 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZI-0003Le-W1; Thu, 09 Aug 2018 14:01:32 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:13 +0100 Message-Id: <20180809130115.28951-15-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 14/16] hw/dma/pl080: Correct bug in register address decode logic 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" A bug in the handling of the register address decode logic for the PL08x meant that we were incorrectly treating accesses to the DMA channel registers (DMACCxSrcAddr, DMACCxDestaddr, DMACCxLLI, DMACCxControl, DMACCxConfiguration) as bad offsets. Fix this long-standing bug. Fixes: https://bugs.launchpad.net/qemu/+bug/1637974 Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- This has been around for a long time, identified by code inspection several years ago in the LP bug. Now I have some guest code that actually tries to use the PL08x I can test the fix... --- hw/dma/pl080.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index a7aacad74f0..8f92550392b 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -229,7 +229,7 @@ static uint64_t pl080_read(void *opaque, hwaddr offset, i =3D (offset & 0xe0) >> 5; if (i >=3D s->nchannels) goto bad_offset; - switch (offset >> 2) { + switch ((offset >> 2) & 7) { case 0: /* SrcAddr */ return s->chan[i].src; case 1: /* DestAddr */ @@ -290,7 +290,7 @@ static void pl080_write(void *opaque, hwaddr offset, i =3D (offset & 0xe0) >> 5; if (i >=3D s->nchannels) goto bad_offset; - switch (offset >> 2) { + switch ((offset >> 2) & 7) { case 0: /* SrcAddr */ s->chan[i].src =3D value; break; @@ -308,6 +308,7 @@ static void pl080_write(void *opaque, hwaddr offset, pl080_run(s); break; } + return; } switch (offset >> 2) { case 2: /* IntTCClear */ --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533819975649461.2768645527286; Thu, 9 Aug 2018 06:06:15 -0700 (PDT) Received: from localhost ([::1]:50729 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkdq-0000wO-0W for importer@patchew.org; Thu, 09 Aug 2018 09:06:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47217) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZS-0005yx-1D for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZR-0003PE-2u for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:42 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44230) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZL-0003KI-V7; Thu, 09 Aug 2018 09:01:36 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZJ-0003Lt-SY; Thu, 09 Aug 2018 14:01:33 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:14 +0100 Message-Id: <20180809130115.28951-16-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 15/16] hw/dma/pl080: Remove hw_error() if DMA is enabled 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The PL08x model currently will unconditionally call hw_error() if the DMA engine is enabled by the guest. This has been present since the PL080 model was edded in 2006, and is presumably either unintentional debug code left enabled, or a guard against untested DMA engine code being used. Remove the hw_error(), since we now have a guest which will actually try to use the DMA engine (the self-test binary for the AN505 MPS2 FPGA image). Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- hw/dma/pl080.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 8f92550392b..ef15d3e628d 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -110,7 +110,6 @@ static void pl080_run(PL080State *s) if ((s->conf & PL080_CONF_E) =3D=3D 0) return; =20 -hw_error("DMA active\n"); /* If we are already in the middle of a DMA operation then indicate th= at there may be new DMA requests and return immediately. */ if (s->running) { --=20 2.17.1 From nobody Wed Nov 5 07:53:26 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 (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1533820662487176.94306242333164; Thu, 9 Aug 2018 06:17:42 -0700 (PDT) Received: from localhost ([::1]:50801 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkou-0004ZK-PF for importer@patchew.org; Thu, 09 Aug 2018 09:17:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47326) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fnkZW-00061R-19 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fnkZU-0003SL-O7 for qemu-devel@nongnu.org; Thu, 09 Aug 2018 09:01:46 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:44236) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fnkZL-0003LA-P5; Thu, 09 Aug 2018 09:01:36 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fnkZK-0003MN-Og; Thu, 09 Aug 2018 14:01:34 +0100 From: Peter Maydell To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Date: Thu, 9 Aug 2018 14:01:15 +0100 Message-Id: <20180809130115.28951-17-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180809130115.28951-1-peter.maydell@linaro.org> References: <20180809130115.28951-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 16/16] hw/arm/mps2-tz: Create PL081s and MSCs 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: RDMRC_1 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The AN505 FPGA image includes four PL081 DMA controllers, each of which is gated by a Master Security Controller that allows the guest to prevent a non-secure DMA controller from accessing memory that is used by secure guest code. Create and wire up these devices. Signed-off-by: Peter Maydell --- hw/arm/mps2-tz.c | 101 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 94 insertions(+), 7 deletions(-) diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index 22180c56fb7..7d92bc5fe1c 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -45,7 +45,9 @@ #include "hw/misc/mps2-scc.h" #include "hw/misc/mps2-fpgaio.h" #include "hw/misc/tz-mpc.h" +#include "hw/misc/tz-msc.h" #include "hw/arm/iotkit.h" +#include "hw/dma/pl080.h" #include "hw/devices.h" #include "net/net.h" #include "hw/core/split-irq.h" @@ -75,8 +77,9 @@ typedef struct { UnimplementedDeviceState i2c[4]; UnimplementedDeviceState i2s_audio; UnimplementedDeviceState gpio[4]; - UnimplementedDeviceState dma[4]; UnimplementedDeviceState gfx; + PL080State dma[4]; + TZMSC msc[4]; CMSDKAPBUART uart[5]; SplitIRQ sec_resp_splitter; qemu_or_irq uart_irq_orgate; @@ -273,6 +276,65 @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms,= void *opaque, return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0); } =20 +static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque, + const char *name, hwaddr size) +{ + PL080State *dma =3D opaque; + int i =3D dma - &mms->dma[0]; + SysBusDevice *s; + char *mscname =3D g_strdup_printf("%s-msc", name); + TZMSC *msc =3D &mms->msc[i]; + DeviceState *iotkitdev =3D DEVICE(&mms->iotkit); + MemoryRegion *msc_upstream; + MemoryRegion *msc_downstream; + + /* + * Each DMA device is a PL081 whose transaction master interface + * is guarded by a Master Security Controller. The downstream end of + * the MSC connects to the IoTKit AHB Slave Expansion port, so the + * DMA devices can see all devices and memory that the CPU does. + */ + init_sysbus_child(OBJECT(mms), mscname, msc, sizeof(mms->msc[0]), + TYPE_TZ_MSC); + msc_downstream =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(&mms->iotkit)= , 0); + object_property_set_link(OBJECT(msc), OBJECT(msc_downstream), + "downstream", &error_fatal); + object_property_set_link(OBJECT(msc), OBJECT(mms), + "idau", &error_fatal); + object_property_set_bool(OBJECT(msc), true, "realized", &error_fatal); + + qdev_connect_gpio_out_named(DEVICE(msc), "irq", 0, + qdev_get_gpio_in_named(iotkitdev, + "mscexp_status", i)= ); + qdev_connect_gpio_out_named(iotkitdev, "mscexp_clear", i, + qdev_get_gpio_in_named(DEVICE(msc), + "irq_clear", 0)); + qdev_connect_gpio_out_named(iotkitdev, "mscexp_ns", i, + qdev_get_gpio_in_named(DEVICE(msc), + "cfg_nonsec", 0)); + qdev_connect_gpio_out(DEVICE(&mms->sec_resp_splitter), + ARRAY_SIZE(mms->ppc) + i, + qdev_get_gpio_in_named(DEVICE(msc), + "cfg_sec_resp", 0)); + msc_upstream =3D sysbus_mmio_get_region(SYS_BUS_DEVICE(msc), 0); + + init_sysbus_child(OBJECT(mms), name, dma, sizeof(mms->dma[0]), TYPE_PL= 081); + object_property_set_link(OBJECT(dma), OBJECT(msc_upstream), + "downstream", &error_fatal); + object_property_set_bool(OBJECT(dma), true, "realized", &error_fatal); + + s =3D SYS_BUS_DEVICE(dma); + /* Wire up DMACINTR, DMACINTERR, DMACINTTC */ + sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, + "EXP_IRQ", 58 + i * 3)= ); + sysbus_connect_irq(s, 1, qdev_get_gpio_in_named(iotkitdev, + "EXP_IRQ", 56 + i * 3)= ); + sysbus_connect_irq(s, 2, qdev_get_gpio_in_named(iotkitdev, + "EXP_IRQ", 57 + i * 3)= ); + + return sysbus_mmio_get_region(s, 0); +} + static void mps2tz_common_init(MachineState *machine) { MPS2TZMachineState *mms =3D MPS2TZ_MACHINE(machine); @@ -299,13 +361,14 @@ static void mps2tz_common_init(MachineState *machine) &error_fatal); =20 /* The sec_resp_cfg output from the IoTKit must be split into multiple - * lines, one for each of the PPCs we create here. + * lines, one for each of the PPCs we create here, plus one per MSC. */ object_initialize(&mms->sec_resp_splitter, sizeof(mms->sec_resp_splitt= er), TYPE_SPLIT_IRQ); object_property_add_child(OBJECT(machine), "sec-resp-splitter", OBJECT(&mms->sec_resp_splitter), &error_abor= t); - object_property_set_int(OBJECT(&mms->sec_resp_splitter), 5, + object_property_set_int(OBJECT(&mms->sec_resp_splitter), + ARRAY_SIZE(mms->ppc) + ARRAY_SIZE(mms->msc), "num-lines", &error_fatal); object_property_set_bool(OBJECT(&mms->sec_resp_splitter), true, "realized", &error_fatal); @@ -406,10 +469,10 @@ static void mps2tz_common_init(MachineState *machine) }, { .name =3D "ahb_ppcexp1", .ports =3D { - { "dma0", make_unimp_dev, &mms->dma[0], 0x40110000, 0x1000= }, - { "dma1", make_unimp_dev, &mms->dma[1], 0x40111000, 0x1000= }, - { "dma2", make_unimp_dev, &mms->dma[2], 0x40112000, 0x1000= }, - { "dma3", make_unimp_dev, &mms->dma[3], 0x40113000, 0x1000= }, + { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 }, + { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 }, + { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 }, + { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 }, }, }, }; @@ -490,12 +553,32 @@ static void mps2tz_common_init(MachineState *machine) armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400= 000); } =20 +static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address, + int *iregion, bool *exempt, bool *ns, bool = *nsc) +{ + /* + * The MPS2 TZ FPGA images have IDAUs in them which are connected to + * the Master Security Controllers. Thes have the same logic as + * is used by the IoTKit for the IDAU connected to the CPU, except + * that MSCs don't care about the NSC attribute. + */ + int region =3D extract32(address, 28, 4); + + *ns =3D !(region & 1); + *nsc =3D false; + /* 0xe0000000..0xe00fffff and 0xf0000000..0xf00fffff are exempt */ + *exempt =3D (address & 0xeff00000) =3D=3D 0xe0000000; + *iregion =3D region; +} + static void mps2tz_class_init(ObjectClass *oc, void *data) { MachineClass *mc =3D MACHINE_CLASS(oc); + IDAUInterfaceClass *iic =3D IDAU_INTERFACE_CLASS(oc); =20 mc->init =3D mps2tz_common_init; mc->max_cpus =3D 1; + iic->check =3D mps2_tz_idau_check; } =20 static void mps2tz_an505_class_init(ObjectClass *oc, void *data) @@ -516,6 +599,10 @@ static const TypeInfo mps2tz_info =3D { .instance_size =3D sizeof(MPS2TZMachineState), .class_size =3D sizeof(MPS2TZMachineClass), .class_init =3D mps2tz_class_init, + .interfaces =3D (InterfaceInfo[]) { + { TYPE_IDAU_INTERFACE }, + { } + }, }; =20 static const TypeInfo mps2tz_an505_info =3D { --=20 2.17.1