1344f4b15SPeter Maydell /* 2344f4b15SPeter Maydell * ARM AHB5 TrustZone Memory Protection Controller emulation 3344f4b15SPeter Maydell * 4344f4b15SPeter Maydell * Copyright (c) 2018 Linaro Limited 5344f4b15SPeter Maydell * Written by Peter Maydell 6344f4b15SPeter Maydell * 7344f4b15SPeter Maydell * This program is free software; you can redistribute it and/or modify 8344f4b15SPeter Maydell * it under the terms of the GNU General Public License version 2 or 9344f4b15SPeter Maydell * (at your option) any later version. 10344f4b15SPeter Maydell */ 11344f4b15SPeter Maydell 12344f4b15SPeter Maydell #include "qemu/osdep.h" 13344f4b15SPeter Maydell #include "qemu/log.h" 140b8fa32fSMarkus Armbruster #include "qemu/module.h" 15344f4b15SPeter Maydell #include "qapi/error.h" 16344f4b15SPeter Maydell #include "trace.h" 17344f4b15SPeter Maydell #include "hw/sysbus.h" 18344f4b15SPeter Maydell #include "hw/registerfields.h" 19*64552b6bSMarkus Armbruster #include "hw/irq.h" 20344f4b15SPeter Maydell #include "hw/misc/tz-mpc.h" 21344f4b15SPeter Maydell 22344f4b15SPeter Maydell /* Our IOMMU has two IOMMU indexes, one for secure transactions and one for 23344f4b15SPeter Maydell * non-secure transactions. 24344f4b15SPeter Maydell */ 25344f4b15SPeter Maydell enum { 26344f4b15SPeter Maydell IOMMU_IDX_S, 27344f4b15SPeter Maydell IOMMU_IDX_NS, 28344f4b15SPeter Maydell IOMMU_NUM_INDEXES, 29344f4b15SPeter Maydell }; 30344f4b15SPeter Maydell 31344f4b15SPeter Maydell /* Config registers */ 32344f4b15SPeter Maydell REG32(CTRL, 0x00) 33cdb60998SPeter Maydell FIELD(CTRL, SEC_RESP, 4, 1) 34cdb60998SPeter Maydell FIELD(CTRL, AUTOINC, 8, 1) 35cdb60998SPeter Maydell FIELD(CTRL, LOCKDOWN, 31, 1) 36344f4b15SPeter Maydell REG32(BLK_MAX, 0x10) 37344f4b15SPeter Maydell REG32(BLK_CFG, 0x14) 38344f4b15SPeter Maydell REG32(BLK_IDX, 0x18) 39344f4b15SPeter Maydell REG32(BLK_LUT, 0x1c) 40344f4b15SPeter Maydell REG32(INT_STAT, 0x20) 41cdb60998SPeter Maydell FIELD(INT_STAT, IRQ, 0, 1) 42344f4b15SPeter Maydell REG32(INT_CLEAR, 0x24) 43cdb60998SPeter Maydell FIELD(INT_CLEAR, IRQ, 0, 1) 44344f4b15SPeter Maydell REG32(INT_EN, 0x28) 45cdb60998SPeter Maydell FIELD(INT_EN, IRQ, 0, 1) 46344f4b15SPeter Maydell REG32(INT_INFO1, 0x2c) 47344f4b15SPeter Maydell REG32(INT_INFO2, 0x30) 4857c49a6eSPeter Maydell FIELD(INT_INFO2, HMASTER, 0, 16) 4957c49a6eSPeter Maydell FIELD(INT_INFO2, HNONSEC, 16, 1) 5057c49a6eSPeter Maydell FIELD(INT_INFO2, CFG_NS, 17, 1) 51344f4b15SPeter Maydell REG32(INT_SET, 0x34) 52cdb60998SPeter Maydell FIELD(INT_SET, IRQ, 0, 1) 53344f4b15SPeter Maydell REG32(PIDR4, 0xfd0) 54344f4b15SPeter Maydell REG32(PIDR5, 0xfd4) 55344f4b15SPeter Maydell REG32(PIDR6, 0xfd8) 56344f4b15SPeter Maydell REG32(PIDR7, 0xfdc) 57344f4b15SPeter Maydell REG32(PIDR0, 0xfe0) 58344f4b15SPeter Maydell REG32(PIDR1, 0xfe4) 59344f4b15SPeter Maydell REG32(PIDR2, 0xfe8) 60344f4b15SPeter Maydell REG32(PIDR3, 0xfec) 61344f4b15SPeter Maydell REG32(CIDR0, 0xff0) 62344f4b15SPeter Maydell REG32(CIDR1, 0xff4) 63344f4b15SPeter Maydell REG32(CIDR2, 0xff8) 64344f4b15SPeter Maydell REG32(CIDR3, 0xffc) 65344f4b15SPeter Maydell 66344f4b15SPeter Maydell static const uint8_t tz_mpc_idregs[] = { 67344f4b15SPeter Maydell 0x04, 0x00, 0x00, 0x00, 68344f4b15SPeter Maydell 0x60, 0xb8, 0x1b, 0x00, 69344f4b15SPeter Maydell 0x0d, 0xf0, 0x05, 0xb1, 70344f4b15SPeter Maydell }; 71344f4b15SPeter Maydell 72cdb60998SPeter Maydell static void tz_mpc_irq_update(TZMPC *s) 73cdb60998SPeter Maydell { 74cdb60998SPeter Maydell qemu_set_irq(s->irq, s->int_stat && s->int_en); 75cdb60998SPeter Maydell } 76cdb60998SPeter Maydell 77dd29d068SPeter Maydell static void tz_mpc_iommu_notify(TZMPC *s, uint32_t lutidx, 78dd29d068SPeter Maydell uint32_t oldlut, uint32_t newlut) 79dd29d068SPeter Maydell { 80dd29d068SPeter Maydell /* Called when the LUT word at lutidx has changed from oldlut to newlut; 81dd29d068SPeter Maydell * must call the IOMMU notifiers for the changed blocks. 82dd29d068SPeter Maydell */ 83dd29d068SPeter Maydell IOMMUTLBEntry entry = { 84dd29d068SPeter Maydell .addr_mask = s->blocksize - 1, 85dd29d068SPeter Maydell }; 86dd29d068SPeter Maydell hwaddr addr = lutidx * s->blocksize * 32; 87dd29d068SPeter Maydell int i; 88dd29d068SPeter Maydell 89dd29d068SPeter Maydell for (i = 0; i < 32; i++, addr += s->blocksize) { 90dd29d068SPeter Maydell bool block_is_ns; 91dd29d068SPeter Maydell 92dd29d068SPeter Maydell if (!((oldlut ^ newlut) & (1 << i))) { 93dd29d068SPeter Maydell continue; 94dd29d068SPeter Maydell } 95dd29d068SPeter Maydell /* This changes the mappings for both the S and the NS space, 96dd29d068SPeter Maydell * so we need to do four notifies: an UNMAP then a MAP for each. 97dd29d068SPeter Maydell */ 98dd29d068SPeter Maydell block_is_ns = newlut & (1 << i); 99dd29d068SPeter Maydell 100dd29d068SPeter Maydell trace_tz_mpc_iommu_notify(addr); 101dd29d068SPeter Maydell entry.iova = addr; 102dd29d068SPeter Maydell entry.translated_addr = addr; 103dd29d068SPeter Maydell 104dd29d068SPeter Maydell entry.perm = IOMMU_NONE; 105dd29d068SPeter Maydell memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry); 106dd29d068SPeter Maydell memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry); 107dd29d068SPeter Maydell 108dd29d068SPeter Maydell entry.perm = IOMMU_RW; 109dd29d068SPeter Maydell if (block_is_ns) { 110dd29d068SPeter Maydell entry.target_as = &s->blocked_io_as; 111dd29d068SPeter Maydell } else { 112dd29d068SPeter Maydell entry.target_as = &s->downstream_as; 113dd29d068SPeter Maydell } 114dd29d068SPeter Maydell memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry); 115dd29d068SPeter Maydell if (block_is_ns) { 116dd29d068SPeter Maydell entry.target_as = &s->downstream_as; 117dd29d068SPeter Maydell } else { 118dd29d068SPeter Maydell entry.target_as = &s->blocked_io_as; 119dd29d068SPeter Maydell } 120dd29d068SPeter Maydell memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry); 121dd29d068SPeter Maydell } 122dd29d068SPeter Maydell } 123dd29d068SPeter Maydell 124cdb60998SPeter Maydell static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size) 125cdb60998SPeter Maydell { 126cdb60998SPeter Maydell /* Auto-increment BLK_IDX if necessary */ 127cdb60998SPeter Maydell if (access_size == 4 && (s->ctrl & R_CTRL_AUTOINC_MASK)) { 128cdb60998SPeter Maydell s->blk_idx++; 129cdb60998SPeter Maydell s->blk_idx %= s->blk_max; 130cdb60998SPeter Maydell } 131cdb60998SPeter Maydell } 132cdb60998SPeter Maydell 133344f4b15SPeter Maydell static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr, 134344f4b15SPeter Maydell uint64_t *pdata, 135344f4b15SPeter Maydell unsigned size, MemTxAttrs attrs) 136344f4b15SPeter Maydell { 137cdb60998SPeter Maydell TZMPC *s = TZ_MPC(opaque); 138344f4b15SPeter Maydell uint64_t r; 139344f4b15SPeter Maydell uint32_t offset = addr & ~0x3; 140344f4b15SPeter Maydell 141344f4b15SPeter Maydell if (!attrs.secure && offset < A_PIDR4) { 142344f4b15SPeter Maydell /* NS accesses can only see the ID registers */ 143344f4b15SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 144344f4b15SPeter Maydell "TZ MPC register read: NS access to offset 0x%x\n", 145344f4b15SPeter Maydell offset); 146344f4b15SPeter Maydell r = 0; 147344f4b15SPeter Maydell goto read_out; 148344f4b15SPeter Maydell } 149344f4b15SPeter Maydell 150344f4b15SPeter Maydell switch (offset) { 151cdb60998SPeter Maydell case A_CTRL: 152cdb60998SPeter Maydell r = s->ctrl; 153cdb60998SPeter Maydell break; 154cdb60998SPeter Maydell case A_BLK_MAX: 155619d54a8SPeter Maydell r = s->blk_max - 1; 156cdb60998SPeter Maydell break; 157cdb60998SPeter Maydell case A_BLK_CFG: 158cdb60998SPeter Maydell /* We are never in "init in progress state", so this just indicates 159cdb60998SPeter Maydell * the block size. s->blocksize == (1 << BLK_CFG + 5), so 160cdb60998SPeter Maydell * BLK_CFG == ctz32(s->blocksize) - 5 161cdb60998SPeter Maydell */ 162cdb60998SPeter Maydell r = ctz32(s->blocksize) - 5; 163cdb60998SPeter Maydell break; 164cdb60998SPeter Maydell case A_BLK_IDX: 165cdb60998SPeter Maydell r = s->blk_idx; 166cdb60998SPeter Maydell break; 167cdb60998SPeter Maydell case A_BLK_LUT: 168cdb60998SPeter Maydell r = s->blk_lut[s->blk_idx]; 169cdb60998SPeter Maydell tz_mpc_autoinc_idx(s, size); 170cdb60998SPeter Maydell break; 171cdb60998SPeter Maydell case A_INT_STAT: 172cdb60998SPeter Maydell r = s->int_stat; 173cdb60998SPeter Maydell break; 174cdb60998SPeter Maydell case A_INT_EN: 175cdb60998SPeter Maydell r = s->int_en; 176cdb60998SPeter Maydell break; 177cdb60998SPeter Maydell case A_INT_INFO1: 178cdb60998SPeter Maydell r = s->int_info1; 179cdb60998SPeter Maydell break; 180cdb60998SPeter Maydell case A_INT_INFO2: 181cdb60998SPeter Maydell r = s->int_info2; 182cdb60998SPeter Maydell break; 183344f4b15SPeter Maydell case A_PIDR4: 184344f4b15SPeter Maydell case A_PIDR5: 185344f4b15SPeter Maydell case A_PIDR6: 186344f4b15SPeter Maydell case A_PIDR7: 187344f4b15SPeter Maydell case A_PIDR0: 188344f4b15SPeter Maydell case A_PIDR1: 189344f4b15SPeter Maydell case A_PIDR2: 190344f4b15SPeter Maydell case A_PIDR3: 191344f4b15SPeter Maydell case A_CIDR0: 192344f4b15SPeter Maydell case A_CIDR1: 193344f4b15SPeter Maydell case A_CIDR2: 194344f4b15SPeter Maydell case A_CIDR3: 195344f4b15SPeter Maydell r = tz_mpc_idregs[(offset - A_PIDR4) / 4]; 196344f4b15SPeter Maydell break; 197344f4b15SPeter Maydell case A_INT_CLEAR: 198344f4b15SPeter Maydell case A_INT_SET: 199344f4b15SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 200344f4b15SPeter Maydell "TZ MPC register read: write-only offset 0x%x\n", 201344f4b15SPeter Maydell offset); 202344f4b15SPeter Maydell r = 0; 203344f4b15SPeter Maydell break; 204344f4b15SPeter Maydell default: 205344f4b15SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 206344f4b15SPeter Maydell "TZ MPC register read: bad offset 0x%x\n", offset); 207344f4b15SPeter Maydell r = 0; 208344f4b15SPeter Maydell break; 209344f4b15SPeter Maydell } 210344f4b15SPeter Maydell 211344f4b15SPeter Maydell if (size != 4) { 212344f4b15SPeter Maydell /* None of our registers are read-sensitive (except BLK_LUT, 213344f4b15SPeter Maydell * which can special case the "size not 4" case), so just 214344f4b15SPeter Maydell * pull the right bytes out of the word read result. 215344f4b15SPeter Maydell */ 216344f4b15SPeter Maydell r = extract32(r, (addr & 3) * 8, size * 8); 217344f4b15SPeter Maydell } 218344f4b15SPeter Maydell 219344f4b15SPeter Maydell read_out: 220344f4b15SPeter Maydell trace_tz_mpc_reg_read(addr, r, size); 221344f4b15SPeter Maydell *pdata = r; 222344f4b15SPeter Maydell return MEMTX_OK; 223344f4b15SPeter Maydell } 224344f4b15SPeter Maydell 225344f4b15SPeter Maydell static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr, 226344f4b15SPeter Maydell uint64_t value, 227344f4b15SPeter Maydell unsigned size, MemTxAttrs attrs) 228344f4b15SPeter Maydell { 229cdb60998SPeter Maydell TZMPC *s = TZ_MPC(opaque); 230344f4b15SPeter Maydell uint32_t offset = addr & ~0x3; 231344f4b15SPeter Maydell 232344f4b15SPeter Maydell trace_tz_mpc_reg_write(addr, value, size); 233344f4b15SPeter Maydell 234344f4b15SPeter Maydell if (!attrs.secure && offset < A_PIDR4) { 235344f4b15SPeter Maydell /* NS accesses can only see the ID registers */ 236344f4b15SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 237344f4b15SPeter Maydell "TZ MPC register write: NS access to offset 0x%x\n", 238344f4b15SPeter Maydell offset); 239344f4b15SPeter Maydell return MEMTX_OK; 240344f4b15SPeter Maydell } 241344f4b15SPeter Maydell 242344f4b15SPeter Maydell if (size != 4) { 243344f4b15SPeter Maydell /* Expand the byte or halfword write to a full word size. 244344f4b15SPeter Maydell * In most cases we can do this with zeroes; the exceptions 245344f4b15SPeter Maydell * are CTRL, BLK_IDX and BLK_LUT. 246344f4b15SPeter Maydell */ 247344f4b15SPeter Maydell uint32_t oldval; 248344f4b15SPeter Maydell 249344f4b15SPeter Maydell switch (offset) { 250cdb60998SPeter Maydell case A_CTRL: 251cdb60998SPeter Maydell oldval = s->ctrl; 252cdb60998SPeter Maydell break; 253cdb60998SPeter Maydell case A_BLK_IDX: 254cdb60998SPeter Maydell oldval = s->blk_idx; 255cdb60998SPeter Maydell break; 256cdb60998SPeter Maydell case A_BLK_LUT: 257cdb60998SPeter Maydell oldval = s->blk_lut[s->blk_idx]; 258cdb60998SPeter Maydell break; 259344f4b15SPeter Maydell default: 260344f4b15SPeter Maydell oldval = 0; 261344f4b15SPeter Maydell break; 262344f4b15SPeter Maydell } 263344f4b15SPeter Maydell value = deposit32(oldval, (addr & 3) * 8, size * 8, value); 264344f4b15SPeter Maydell } 265344f4b15SPeter Maydell 266cdb60998SPeter Maydell if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) && 267cdb60998SPeter Maydell (offset == A_CTRL || offset == A_BLK_LUT || offset == A_INT_EN)) { 268cdb60998SPeter Maydell /* Lockdown mode makes these three registers read-only, and 269cdb60998SPeter Maydell * the only way out of it is to reset the device. 270cdb60998SPeter Maydell */ 271cdb60998SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x%x " 272cdb60998SPeter Maydell "while MPC is in lockdown mode\n", offset); 273cdb60998SPeter Maydell return MEMTX_OK; 274cdb60998SPeter Maydell } 275cdb60998SPeter Maydell 276344f4b15SPeter Maydell switch (offset) { 277cdb60998SPeter Maydell case A_CTRL: 278cdb60998SPeter Maydell /* We don't implement the 'data gating' feature so all other bits 279cdb60998SPeter Maydell * are reserved and we make them RAZ/WI. 280cdb60998SPeter Maydell */ 281cdb60998SPeter Maydell s->ctrl = value & (R_CTRL_SEC_RESP_MASK | 282cdb60998SPeter Maydell R_CTRL_AUTOINC_MASK | 283cdb60998SPeter Maydell R_CTRL_LOCKDOWN_MASK); 284cdb60998SPeter Maydell break; 285cdb60998SPeter Maydell case A_BLK_IDX: 286cdb60998SPeter Maydell s->blk_idx = value % s->blk_max; 287cdb60998SPeter Maydell break; 288cdb60998SPeter Maydell case A_BLK_LUT: 289dd29d068SPeter Maydell tz_mpc_iommu_notify(s, s->blk_idx, s->blk_lut[s->blk_idx], value); 290cdb60998SPeter Maydell s->blk_lut[s->blk_idx] = value; 291cdb60998SPeter Maydell tz_mpc_autoinc_idx(s, size); 292cdb60998SPeter Maydell break; 293cdb60998SPeter Maydell case A_INT_CLEAR: 294cdb60998SPeter Maydell if (value & R_INT_CLEAR_IRQ_MASK) { 295cdb60998SPeter Maydell s->int_stat = 0; 296cdb60998SPeter Maydell tz_mpc_irq_update(s); 297cdb60998SPeter Maydell } 298cdb60998SPeter Maydell break; 299cdb60998SPeter Maydell case A_INT_EN: 300cdb60998SPeter Maydell s->int_en = value & R_INT_EN_IRQ_MASK; 301cdb60998SPeter Maydell tz_mpc_irq_update(s); 302cdb60998SPeter Maydell break; 303cdb60998SPeter Maydell case A_INT_SET: 304cdb60998SPeter Maydell if (value & R_INT_SET_IRQ_MASK) { 305cdb60998SPeter Maydell s->int_stat = R_INT_STAT_IRQ_MASK; 306cdb60998SPeter Maydell tz_mpc_irq_update(s); 307cdb60998SPeter Maydell } 308cdb60998SPeter Maydell break; 309344f4b15SPeter Maydell case A_PIDR4: 310344f4b15SPeter Maydell case A_PIDR5: 311344f4b15SPeter Maydell case A_PIDR6: 312344f4b15SPeter Maydell case A_PIDR7: 313344f4b15SPeter Maydell case A_PIDR0: 314344f4b15SPeter Maydell case A_PIDR1: 315344f4b15SPeter Maydell case A_PIDR2: 316344f4b15SPeter Maydell case A_PIDR3: 317344f4b15SPeter Maydell case A_CIDR0: 318344f4b15SPeter Maydell case A_CIDR1: 319344f4b15SPeter Maydell case A_CIDR2: 320344f4b15SPeter Maydell case A_CIDR3: 321344f4b15SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 322344f4b15SPeter Maydell "TZ MPC register write: read-only offset 0x%x\n", offset); 323344f4b15SPeter Maydell break; 324344f4b15SPeter Maydell default: 325344f4b15SPeter Maydell qemu_log_mask(LOG_GUEST_ERROR, 326344f4b15SPeter Maydell "TZ MPC register write: bad offset 0x%x\n", offset); 327344f4b15SPeter Maydell break; 328344f4b15SPeter Maydell } 329344f4b15SPeter Maydell 330344f4b15SPeter Maydell return MEMTX_OK; 331344f4b15SPeter Maydell } 332344f4b15SPeter Maydell 333344f4b15SPeter Maydell static const MemoryRegionOps tz_mpc_reg_ops = { 334344f4b15SPeter Maydell .read_with_attrs = tz_mpc_reg_read, 335344f4b15SPeter Maydell .write_with_attrs = tz_mpc_reg_write, 336344f4b15SPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 337344f4b15SPeter Maydell .valid.min_access_size = 1, 338344f4b15SPeter Maydell .valid.max_access_size = 4, 339344f4b15SPeter Maydell .impl.min_access_size = 1, 340344f4b15SPeter Maydell .impl.max_access_size = 4, 341344f4b15SPeter Maydell }; 342344f4b15SPeter Maydell 34357c49a6eSPeter Maydell static inline bool tz_mpc_cfg_ns(TZMPC *s, hwaddr addr) 34457c49a6eSPeter Maydell { 34557c49a6eSPeter Maydell /* Return the cfg_ns bit from the LUT for the specified address */ 34657c49a6eSPeter Maydell hwaddr blknum = addr / s->blocksize; 34757c49a6eSPeter Maydell hwaddr blkword = blknum / 32; 34857c49a6eSPeter Maydell uint32_t blkbit = 1U << (blknum % 32); 34957c49a6eSPeter Maydell 35057c49a6eSPeter Maydell /* This would imply the address was larger than the size we 35157c49a6eSPeter Maydell * defined this memory region to be, so it can't happen. 35257c49a6eSPeter Maydell */ 35357c49a6eSPeter Maydell assert(blkword < s->blk_max); 35457c49a6eSPeter Maydell return s->blk_lut[blkword] & blkbit; 35557c49a6eSPeter Maydell } 35657c49a6eSPeter Maydell 35757c49a6eSPeter Maydell static MemTxResult tz_mpc_handle_block(TZMPC *s, hwaddr addr, MemTxAttrs attrs) 35857c49a6eSPeter Maydell { 35957c49a6eSPeter Maydell /* Handle a blocked transaction: raise IRQ, capture info, etc */ 36057c49a6eSPeter Maydell if (!s->int_stat) { 36157c49a6eSPeter Maydell /* First blocked transfer: capture information into INT_INFO1 and 36257c49a6eSPeter Maydell * INT_INFO2. Subsequent transfers are still blocked but don't 36357c49a6eSPeter Maydell * capture information until the guest clears the interrupt. 36457c49a6eSPeter Maydell */ 36557c49a6eSPeter Maydell 36657c49a6eSPeter Maydell s->int_info1 = addr; 36757c49a6eSPeter Maydell s->int_info2 = 0; 36857c49a6eSPeter Maydell s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HMASTER, 36957c49a6eSPeter Maydell attrs.requester_id & 0xffff); 37057c49a6eSPeter Maydell s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HNONSEC, 37157c49a6eSPeter Maydell ~attrs.secure); 37257c49a6eSPeter Maydell s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, CFG_NS, 37357c49a6eSPeter Maydell tz_mpc_cfg_ns(s, addr)); 37457c49a6eSPeter Maydell s->int_stat |= R_INT_STAT_IRQ_MASK; 37557c49a6eSPeter Maydell tz_mpc_irq_update(s); 37657c49a6eSPeter Maydell } 37757c49a6eSPeter Maydell 37857c49a6eSPeter Maydell /* Generate bus error if desired; otherwise RAZ/WI */ 37957c49a6eSPeter Maydell return (s->ctrl & R_CTRL_SEC_RESP_MASK) ? MEMTX_ERROR : MEMTX_OK; 38057c49a6eSPeter Maydell } 38157c49a6eSPeter Maydell 382344f4b15SPeter Maydell /* Accesses only reach these read and write functions if the MPC is 383344f4b15SPeter Maydell * blocking them; non-blocked accesses go directly to the downstream 384344f4b15SPeter Maydell * memory region without passing through this code. 385344f4b15SPeter Maydell */ 386344f4b15SPeter Maydell static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr, 387344f4b15SPeter Maydell uint64_t *pdata, 388344f4b15SPeter Maydell unsigned size, MemTxAttrs attrs) 389344f4b15SPeter Maydell { 39057c49a6eSPeter Maydell TZMPC *s = TZ_MPC(opaque); 39157c49a6eSPeter Maydell 392344f4b15SPeter Maydell trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure); 393344f4b15SPeter Maydell 394344f4b15SPeter Maydell *pdata = 0; 39557c49a6eSPeter Maydell return tz_mpc_handle_block(s, addr, attrs); 396344f4b15SPeter Maydell } 397344f4b15SPeter Maydell 398344f4b15SPeter Maydell static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr, 399344f4b15SPeter Maydell uint64_t value, 400344f4b15SPeter Maydell unsigned size, MemTxAttrs attrs) 401344f4b15SPeter Maydell { 40257c49a6eSPeter Maydell TZMPC *s = TZ_MPC(opaque); 40357c49a6eSPeter Maydell 404344f4b15SPeter Maydell trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure); 405344f4b15SPeter Maydell 40657c49a6eSPeter Maydell return tz_mpc_handle_block(s, addr, attrs); 407344f4b15SPeter Maydell } 408344f4b15SPeter Maydell 409344f4b15SPeter Maydell static const MemoryRegionOps tz_mpc_mem_blocked_ops = { 410344f4b15SPeter Maydell .read_with_attrs = tz_mpc_mem_blocked_read, 411344f4b15SPeter Maydell .write_with_attrs = tz_mpc_mem_blocked_write, 412344f4b15SPeter Maydell .endianness = DEVICE_LITTLE_ENDIAN, 413344f4b15SPeter Maydell .valid.min_access_size = 1, 414344f4b15SPeter Maydell .valid.max_access_size = 8, 415344f4b15SPeter Maydell .impl.min_access_size = 1, 416344f4b15SPeter Maydell .impl.max_access_size = 8, 417344f4b15SPeter Maydell }; 418344f4b15SPeter Maydell 419344f4b15SPeter Maydell static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu, 420344f4b15SPeter Maydell hwaddr addr, IOMMUAccessFlags flags, 421344f4b15SPeter Maydell int iommu_idx) 422344f4b15SPeter Maydell { 423344f4b15SPeter Maydell TZMPC *s = TZ_MPC(container_of(iommu, TZMPC, upstream)); 424344f4b15SPeter Maydell bool ok; 425344f4b15SPeter Maydell 426344f4b15SPeter Maydell IOMMUTLBEntry ret = { 427344f4b15SPeter Maydell .iova = addr & ~(s->blocksize - 1), 428344f4b15SPeter Maydell .translated_addr = addr & ~(s->blocksize - 1), 429344f4b15SPeter Maydell .addr_mask = s->blocksize - 1, 430344f4b15SPeter Maydell .perm = IOMMU_RW, 431344f4b15SPeter Maydell }; 432344f4b15SPeter Maydell 433344f4b15SPeter Maydell /* Look at the per-block configuration for this address, and 434344f4b15SPeter Maydell * return a TLB entry directing the transaction at either 435344f4b15SPeter Maydell * downstream_as or blocked_io_as, as appropriate. 436dd29d068SPeter Maydell * If the LUT cfg_ns bit is 1, only non-secure transactions 437dd29d068SPeter Maydell * may pass. If the bit is 0, only secure transactions may pass. 438344f4b15SPeter Maydell */ 439dd29d068SPeter Maydell ok = tz_mpc_cfg_ns(s, addr) == (iommu_idx == IOMMU_IDX_NS); 440344f4b15SPeter Maydell 441344f4b15SPeter Maydell trace_tz_mpc_translate(addr, flags, 442344f4b15SPeter Maydell iommu_idx == IOMMU_IDX_S ? "S" : "NS", 443344f4b15SPeter Maydell ok ? "pass" : "block"); 444344f4b15SPeter Maydell 445344f4b15SPeter Maydell ret.target_as = ok ? &s->downstream_as : &s->blocked_io_as; 446344f4b15SPeter Maydell return ret; 447344f4b15SPeter Maydell } 448344f4b15SPeter Maydell 449344f4b15SPeter Maydell static int tz_mpc_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attrs) 450344f4b15SPeter Maydell { 451344f4b15SPeter Maydell /* We treat unspecified attributes like secure. Transactions with 452344f4b15SPeter Maydell * unspecified attributes come from places like 4533c8133f9SPeter Maydell * rom_reset() for initial image load, and we want 454344f4b15SPeter Maydell * those to pass through the from-reset "everything is secure" config. 455344f4b15SPeter Maydell * All the real during-emulation transactions from the CPU will 456344f4b15SPeter Maydell * specify attributes. 457344f4b15SPeter Maydell */ 458344f4b15SPeter Maydell return (attrs.unspecified || attrs.secure) ? IOMMU_IDX_S : IOMMU_IDX_NS; 459344f4b15SPeter Maydell } 460344f4b15SPeter Maydell 461344f4b15SPeter Maydell static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu) 462344f4b15SPeter Maydell { 463344f4b15SPeter Maydell return IOMMU_NUM_INDEXES; 464344f4b15SPeter Maydell } 465344f4b15SPeter Maydell 466344f4b15SPeter Maydell static void tz_mpc_reset(DeviceState *dev) 467344f4b15SPeter Maydell { 468cdb60998SPeter Maydell TZMPC *s = TZ_MPC(dev); 469cdb60998SPeter Maydell 470cdb60998SPeter Maydell s->ctrl = 0x00000100; 471cdb60998SPeter Maydell s->blk_idx = 0; 472cdb60998SPeter Maydell s->int_stat = 0; 473cdb60998SPeter Maydell s->int_en = 1; 474cdb60998SPeter Maydell s->int_info1 = 0; 475cdb60998SPeter Maydell s->int_info2 = 0; 476cdb60998SPeter Maydell 477cdb60998SPeter Maydell memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t)); 478344f4b15SPeter Maydell } 479344f4b15SPeter Maydell 480344f4b15SPeter Maydell static void tz_mpc_init(Object *obj) 481344f4b15SPeter Maydell { 482344f4b15SPeter Maydell DeviceState *dev = DEVICE(obj); 483344f4b15SPeter Maydell TZMPC *s = TZ_MPC(obj); 484344f4b15SPeter Maydell 485344f4b15SPeter Maydell qdev_init_gpio_out_named(dev, &s->irq, "irq", 1); 486344f4b15SPeter Maydell } 487344f4b15SPeter Maydell 488344f4b15SPeter Maydell static void tz_mpc_realize(DeviceState *dev, Error **errp) 489344f4b15SPeter Maydell { 490344f4b15SPeter Maydell Object *obj = OBJECT(dev); 491344f4b15SPeter Maydell SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 492344f4b15SPeter Maydell TZMPC *s = TZ_MPC(dev); 493344f4b15SPeter Maydell uint64_t size; 494344f4b15SPeter Maydell 495344f4b15SPeter Maydell /* We can't create the upstream end of the port until realize, 496344f4b15SPeter Maydell * as we don't know the size of the MR used as the downstream until then. 497344f4b15SPeter Maydell * We insist on having a downstream, to avoid complicating the code 498344f4b15SPeter Maydell * with handling the "don't know how big this is" case. It's easy 499344f4b15SPeter Maydell * enough for the user to create an unimplemented_device as downstream 500344f4b15SPeter Maydell * if they have nothing else to plug into this. 501344f4b15SPeter Maydell */ 502344f4b15SPeter Maydell if (!s->downstream) { 503344f4b15SPeter Maydell error_setg(errp, "MPC 'downstream' link not set"); 504344f4b15SPeter Maydell return; 505344f4b15SPeter Maydell } 506344f4b15SPeter Maydell 507344f4b15SPeter Maydell size = memory_region_size(s->downstream); 508344f4b15SPeter Maydell 509344f4b15SPeter Maydell memory_region_init_iommu(&s->upstream, sizeof(s->upstream), 510344f4b15SPeter Maydell TYPE_TZ_MPC_IOMMU_MEMORY_REGION, 511344f4b15SPeter Maydell obj, "tz-mpc-upstream", size); 512344f4b15SPeter Maydell 513344f4b15SPeter Maydell /* In real hardware the block size is configurable. In QEMU we could 514344f4b15SPeter Maydell * make it configurable but will need it to be at least as big as the 515344f4b15SPeter Maydell * target page size so we can execute out of the resulting MRs. Guest 516344f4b15SPeter Maydell * software is supposed to check the block size using the BLK_CFG 517344f4b15SPeter Maydell * register, so make it fixed at the page size. 518344f4b15SPeter Maydell */ 519344f4b15SPeter Maydell s->blocksize = memory_region_iommu_get_min_page_size(&s->upstream); 520344f4b15SPeter Maydell if (size % s->blocksize != 0) { 521344f4b15SPeter Maydell error_setg(errp, 522344f4b15SPeter Maydell "MPC 'downstream' size %" PRId64 523344f4b15SPeter Maydell " is not a multiple of %" HWADDR_PRIx " bytes", 524344f4b15SPeter Maydell size, s->blocksize); 525344f4b15SPeter Maydell object_unref(OBJECT(&s->upstream)); 526344f4b15SPeter Maydell return; 527344f4b15SPeter Maydell } 528344f4b15SPeter Maydell 529344f4b15SPeter Maydell /* BLK_MAX is the max value of BLK_IDX, which indexes an array of 32-bit 530344f4b15SPeter Maydell * words, each bit of which indicates one block. 531344f4b15SPeter Maydell */ 532344f4b15SPeter Maydell s->blk_max = DIV_ROUND_UP(size / s->blocksize, 32); 533344f4b15SPeter Maydell 534344f4b15SPeter Maydell memory_region_init_io(&s->regmr, obj, &tz_mpc_reg_ops, 535344f4b15SPeter Maydell s, "tz-mpc-regs", 0x1000); 536344f4b15SPeter Maydell sysbus_init_mmio(sbd, &s->regmr); 537344f4b15SPeter Maydell 538344f4b15SPeter Maydell sysbus_init_mmio(sbd, MEMORY_REGION(&s->upstream)); 539344f4b15SPeter Maydell 540344f4b15SPeter Maydell /* This memory region is not exposed to users of this device as a 541344f4b15SPeter Maydell * sysbus MMIO region, but is instead used internally as something 542344f4b15SPeter Maydell * that our IOMMU translate function might direct accesses to. 543344f4b15SPeter Maydell */ 544344f4b15SPeter Maydell memory_region_init_io(&s->blocked_io, obj, &tz_mpc_mem_blocked_ops, 545344f4b15SPeter Maydell s, "tz-mpc-blocked-io", size); 546344f4b15SPeter Maydell 547344f4b15SPeter Maydell address_space_init(&s->downstream_as, s->downstream, 548344f4b15SPeter Maydell "tz-mpc-downstream"); 549344f4b15SPeter Maydell address_space_init(&s->blocked_io_as, &s->blocked_io, 550344f4b15SPeter Maydell "tz-mpc-blocked-io"); 551cdb60998SPeter Maydell 552218fe5ceSPeter Maydell s->blk_lut = g_new0(uint32_t, s->blk_max); 553cdb60998SPeter Maydell } 554cdb60998SPeter Maydell 555cdb60998SPeter Maydell static int tz_mpc_post_load(void *opaque, int version_id) 556cdb60998SPeter Maydell { 557cdb60998SPeter Maydell TZMPC *s = TZ_MPC(opaque); 558cdb60998SPeter Maydell 559cdb60998SPeter Maydell /* Check the incoming data doesn't point blk_idx off the end of blk_lut. */ 560cdb60998SPeter Maydell if (s->blk_idx >= s->blk_max) { 561cdb60998SPeter Maydell return -1; 562cdb60998SPeter Maydell } 563cdb60998SPeter Maydell return 0; 564344f4b15SPeter Maydell } 565344f4b15SPeter Maydell 566344f4b15SPeter Maydell static const VMStateDescription tz_mpc_vmstate = { 567344f4b15SPeter Maydell .name = "tz-mpc", 568344f4b15SPeter Maydell .version_id = 1, 569344f4b15SPeter Maydell .minimum_version_id = 1, 570cdb60998SPeter Maydell .post_load = tz_mpc_post_load, 571344f4b15SPeter Maydell .fields = (VMStateField[]) { 572cdb60998SPeter Maydell VMSTATE_UINT32(ctrl, TZMPC), 573cdb60998SPeter Maydell VMSTATE_UINT32(blk_idx, TZMPC), 574cdb60998SPeter Maydell VMSTATE_UINT32(int_stat, TZMPC), 575cdb60998SPeter Maydell VMSTATE_UINT32(int_en, TZMPC), 576cdb60998SPeter Maydell VMSTATE_UINT32(int_info1, TZMPC), 577cdb60998SPeter Maydell VMSTATE_UINT32(int_info2, TZMPC), 578cdb60998SPeter Maydell VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max, 579cdb60998SPeter Maydell 0, vmstate_info_uint32, uint32_t), 580344f4b15SPeter Maydell VMSTATE_END_OF_LIST() 581344f4b15SPeter Maydell } 582344f4b15SPeter Maydell }; 583344f4b15SPeter Maydell 584344f4b15SPeter Maydell static Property tz_mpc_properties[] = { 585344f4b15SPeter Maydell DEFINE_PROP_LINK("downstream", TZMPC, downstream, 586344f4b15SPeter Maydell TYPE_MEMORY_REGION, MemoryRegion *), 587344f4b15SPeter Maydell DEFINE_PROP_END_OF_LIST(), 588344f4b15SPeter Maydell }; 589344f4b15SPeter Maydell 590344f4b15SPeter Maydell static void tz_mpc_class_init(ObjectClass *klass, void *data) 591344f4b15SPeter Maydell { 592344f4b15SPeter Maydell DeviceClass *dc = DEVICE_CLASS(klass); 593344f4b15SPeter Maydell 594344f4b15SPeter Maydell dc->realize = tz_mpc_realize; 595344f4b15SPeter Maydell dc->vmsd = &tz_mpc_vmstate; 596344f4b15SPeter Maydell dc->reset = tz_mpc_reset; 597344f4b15SPeter Maydell dc->props = tz_mpc_properties; 598344f4b15SPeter Maydell } 599344f4b15SPeter Maydell 600344f4b15SPeter Maydell static const TypeInfo tz_mpc_info = { 601344f4b15SPeter Maydell .name = TYPE_TZ_MPC, 602344f4b15SPeter Maydell .parent = TYPE_SYS_BUS_DEVICE, 603344f4b15SPeter Maydell .instance_size = sizeof(TZMPC), 604344f4b15SPeter Maydell .instance_init = tz_mpc_init, 605344f4b15SPeter Maydell .class_init = tz_mpc_class_init, 606344f4b15SPeter Maydell }; 607344f4b15SPeter Maydell 608344f4b15SPeter Maydell static void tz_mpc_iommu_memory_region_class_init(ObjectClass *klass, 609344f4b15SPeter Maydell void *data) 610344f4b15SPeter Maydell { 611344f4b15SPeter Maydell IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); 612344f4b15SPeter Maydell 613344f4b15SPeter Maydell imrc->translate = tz_mpc_translate; 614344f4b15SPeter Maydell imrc->attrs_to_index = tz_mpc_attrs_to_index; 615344f4b15SPeter Maydell imrc->num_indexes = tz_mpc_num_indexes; 616344f4b15SPeter Maydell } 617344f4b15SPeter Maydell 618344f4b15SPeter Maydell static const TypeInfo tz_mpc_iommu_memory_region_info = { 619344f4b15SPeter Maydell .name = TYPE_TZ_MPC_IOMMU_MEMORY_REGION, 620344f4b15SPeter Maydell .parent = TYPE_IOMMU_MEMORY_REGION, 621344f4b15SPeter Maydell .class_init = tz_mpc_iommu_memory_region_class_init, 622344f4b15SPeter Maydell }; 623344f4b15SPeter Maydell 624344f4b15SPeter Maydell static void tz_mpc_register_types(void) 625344f4b15SPeter Maydell { 626344f4b15SPeter Maydell type_register_static(&tz_mpc_info); 627344f4b15SPeter Maydell type_register_static(&tz_mpc_iommu_memory_region_info); 628344f4b15SPeter Maydell } 629344f4b15SPeter Maydell 630344f4b15SPeter Maydell type_init(tz_mpc_register_types); 631