From nobody Mon Feb 9 14:35:51 2026 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 152967314251479.47102991345355; Fri, 22 Jun 2018 06:12:22 -0700 (PDT) Received: from localhost ([::1]:33748 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fWLrM-0006Rb-Pe for importer@patchew.org; Fri, 22 Jun 2018 09:12:16 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49980) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fWLd3-0003V8-VQ for qemu-devel@nongnu.org; Fri, 22 Jun 2018 08:57:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fWLd2-0005M2-Gq for qemu-devel@nongnu.org; Fri, 22 Jun 2018 08:57:30 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:42960) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fWLd2-00055S-82 for qemu-devel@nongnu.org; Fri, 22 Jun 2018 08:57:28 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from ) id 1fWLd0-0003wr-UG for qemu-devel@nongnu.org; Fri, 22 Jun 2018 13:57:26 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Fri, 22 Jun 2018 13:57:03 +0100 Message-Id: <20180622125713.15303-19-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180622125713.15303-1-peter.maydell@linaro.org> References: <20180622125713.15303-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] [PULL 18/28] hw/misc/tz-mpc.c: Implement registers X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Implement the missing registers for the TZ MPC. Signed-off-by: Peter Maydell Reviewed-by: Eric Auger Message-id: 20180620132032.28865-3-peter.maydell@linaro.org --- include/hw/misc/tz-mpc.h | 10 +++ hw/misc/tz-mpc.c | 140 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h index d1a65fd9a38..6f15945410d 100644 --- a/include/hw/misc/tz-mpc.h +++ b/include/hw/misc/tz-mpc.h @@ -48,6 +48,16 @@ struct TZMPC { =20 /*< public >*/ =20 + /* State */ + uint32_t ctrl; + uint32_t blk_idx; + uint32_t int_stat; + uint32_t int_en; + uint32_t int_info1; + uint32_t int_info2; + + uint32_t *blk_lut; + qemu_irq irq; =20 /* Properties */ diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c index 8a8617bdbdf..e5b91bf81a3 100644 --- a/hw/misc/tz-mpc.c +++ b/hw/misc/tz-mpc.c @@ -28,16 +28,23 @@ enum { =20 /* Config registers */ REG32(CTRL, 0x00) + FIELD(CTRL, SEC_RESP, 4, 1) + FIELD(CTRL, AUTOINC, 8, 1) + FIELD(CTRL, LOCKDOWN, 31, 1) REG32(BLK_MAX, 0x10) REG32(BLK_CFG, 0x14) REG32(BLK_IDX, 0x18) REG32(BLK_LUT, 0x1c) REG32(INT_STAT, 0x20) + FIELD(INT_STAT, IRQ, 0, 1) REG32(INT_CLEAR, 0x24) + FIELD(INT_CLEAR, IRQ, 0, 1) REG32(INT_EN, 0x28) + FIELD(INT_EN, IRQ, 0, 1) REG32(INT_INFO1, 0x2c) REG32(INT_INFO2, 0x30) REG32(INT_SET, 0x34) + FIELD(INT_SET, IRQ, 0, 1) REG32(PIDR4, 0xfd0) REG32(PIDR5, 0xfd4) REG32(PIDR6, 0xfd8) @@ -57,10 +64,25 @@ static const uint8_t tz_mpc_idregs[] =3D { 0x0d, 0xf0, 0x05, 0xb1, }; =20 +static void tz_mpc_irq_update(TZMPC *s) +{ + qemu_set_irq(s->irq, s->int_stat && s->int_en); +} + +static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size) +{ + /* Auto-increment BLK_IDX if necessary */ + if (access_size =3D=3D 4 && (s->ctrl & R_CTRL_AUTOINC_MASK)) { + s->blk_idx++; + s->blk_idx %=3D s->blk_max; + } +} + static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr, uint64_t *pdata, unsigned size, MemTxAttrs attrs) { + TZMPC *s =3D TZ_MPC(opaque); uint64_t r; uint32_t offset =3D addr & ~0x3; =20 @@ -74,6 +96,38 @@ static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr = addr, } =20 switch (offset) { + case A_CTRL: + r =3D s->ctrl; + break; + case A_BLK_MAX: + r =3D s->blk_max; + break; + case A_BLK_CFG: + /* We are never in "init in progress state", so this just indicates + * the block size. s->blocksize =3D=3D (1 << BLK_CFG + 5), so + * BLK_CFG =3D=3D ctz32(s->blocksize) - 5 + */ + r =3D ctz32(s->blocksize) - 5; + break; + case A_BLK_IDX: + r =3D s->blk_idx; + break; + case A_BLK_LUT: + r =3D s->blk_lut[s->blk_idx]; + tz_mpc_autoinc_idx(s, size); + break; + case A_INT_STAT: + r =3D s->int_stat; + break; + case A_INT_EN: + r =3D s->int_en; + break; + case A_INT_INFO1: + r =3D s->int_info1; + break; + case A_INT_INFO2: + r =3D s->int_info2; + break; case A_PIDR4: case A_PIDR5: case A_PIDR6: @@ -120,6 +174,7 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwadd= r addr, uint64_t value, unsigned size, MemTxAttrs attrs) { + TZMPC *s =3D TZ_MPC(opaque); uint32_t offset =3D addr & ~0x3; =20 trace_tz_mpc_reg_write(addr, value, size); @@ -140,9 +195,15 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwad= dr addr, uint32_t oldval; =20 switch (offset) { - /* As we add support for registers which need expansions - * other than zeroes we'll fill in cases here. - */ + case A_CTRL: + oldval =3D s->ctrl; + break; + case A_BLK_IDX: + oldval =3D s->blk_idx; + break; + case A_BLK_LUT: + oldval =3D s->blk_lut[s->blk_idx]; + break; default: oldval =3D 0; break; @@ -150,7 +211,48 @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwad= dr addr, value =3D deposit32(oldval, (addr & 3) * 8, size * 8, value); } =20 + if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) && + (offset =3D=3D A_CTRL || offset =3D=3D A_BLK_LUT || offset =3D=3D = A_INT_EN)) { + /* Lockdown mode makes these three registers read-only, and + * the only way out of it is to reset the device. + */ + qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x= %x " + "while MPC is in lockdown mode\n", offset); + return MEMTX_OK; + } + switch (offset) { + case A_CTRL: + /* We don't implement the 'data gating' feature so all other bits + * are reserved and we make them RAZ/WI. + */ + s->ctrl =3D value & (R_CTRL_SEC_RESP_MASK | + R_CTRL_AUTOINC_MASK | + R_CTRL_LOCKDOWN_MASK); + break; + case A_BLK_IDX: + s->blk_idx =3D value % s->blk_max; + break; + case A_BLK_LUT: + s->blk_lut[s->blk_idx] =3D value; + tz_mpc_autoinc_idx(s, size); + break; + case A_INT_CLEAR: + if (value & R_INT_CLEAR_IRQ_MASK) { + s->int_stat =3D 0; + tz_mpc_irq_update(s); + } + break; + case A_INT_EN: + s->int_en =3D value & R_INT_EN_IRQ_MASK; + tz_mpc_irq_update(s); + break; + case A_INT_SET: + if (value & R_INT_SET_IRQ_MASK) { + s->int_stat =3D R_INT_STAT_IRQ_MASK; + tz_mpc_irq_update(s); + } + break; case A_PIDR4: case A_PIDR5: case A_PIDR6: @@ -266,6 +368,16 @@ static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu) =20 static void tz_mpc_reset(DeviceState *dev) { + TZMPC *s =3D TZ_MPC(dev); + + s->ctrl =3D 0x00000100; + s->blk_idx =3D 0; + s->int_stat =3D 0; + s->int_en =3D 1; + s->int_info1 =3D 0; + s->int_info2 =3D 0; + + memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t)); } =20 static void tz_mpc_init(Object *obj) @@ -339,13 +451,35 @@ static void tz_mpc_realize(DeviceState *dev, Error **= errp) "tz-mpc-downstream"); address_space_init(&s->blocked_io_as, &s->blocked_io, "tz-mpc-blocked-io"); + + s->blk_lut =3D g_new(uint32_t, s->blk_max); +} + +static int tz_mpc_post_load(void *opaque, int version_id) +{ + TZMPC *s =3D TZ_MPC(opaque); + + /* Check the incoming data doesn't point blk_idx off the end of blk_lu= t. */ + if (s->blk_idx >=3D s->blk_max) { + return -1; + } + return 0; } =20 static const VMStateDescription tz_mpc_vmstate =3D { .name =3D "tz-mpc", .version_id =3D 1, .minimum_version_id =3D 1, + .post_load =3D tz_mpc_post_load, .fields =3D (VMStateField[]) { + VMSTATE_UINT32(ctrl, TZMPC), + VMSTATE_UINT32(blk_idx, TZMPC), + VMSTATE_UINT32(int_stat, TZMPC), + VMSTATE_UINT32(int_en, TZMPC), + VMSTATE_UINT32(int_info1, TZMPC), + VMSTATE_UINT32(int_info2, TZMPC), + VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max, + 0, vmstate_info_uint32, uint32_t), VMSTATE_END_OF_LIST() } }; --=20 2.17.1