diff options
author | Wen, Jianxian <Jianxian.Wen@verisilicon.com> | 2021-08-18 10:17:00 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-08-25 10:48:50 +0100 |
commit | 77844cc51aa0714d54ae6f5a12279ce0e7f5ef55 (patch) | |
tree | de778196460fc924fbf591d8694bce77ffa351e5 /hw/dma | |
parent | ff31cca71ef257f8da2d9bc647ddd53f080ce580 (diff) |
hw/dma/pl330: Add memory region to replace default
Add property memory region which can connect with IOMMU region to support SMMU translate.
Signed-off-by: Jianxian Wen <jianxian.wen@verisilicon.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 4C23C17B8E87E74E906A25A3254A03F4FA1FEC31@SHASXM03.verisilicon.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/dma')
-rw-r--r-- | hw/dma/pl330.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index 944ba296b0..0cb46191c1 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -269,6 +269,9 @@ struct PL330State { uint8_t num_faulting; uint8_t periph_busy[PL330_PERIPH_NUM]; + /* Memory region that DMA operation access */ + MemoryRegion *mem_mr; + AddressSpace *mem_as; }; #define TYPE_PL330 "pl330" @@ -1108,7 +1111,7 @@ static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch) uint8_t opcode; int i; - dma_memory_read(&address_space_memory, ch->pc, &opcode, 1); + dma_memory_read(ch->parent->mem_as, ch->pc, &opcode, 1); for (i = 0; insn_desc[i].size; i++) { if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) { return &insn_desc[i]; @@ -1122,7 +1125,7 @@ static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn) uint8_t buf[PL330_INSN_MAXSIZE]; assert(insn->size <= PL330_INSN_MAXSIZE); - dma_memory_read(&address_space_memory, ch->pc, buf, insn->size); + dma_memory_read(ch->parent->mem_as, ch->pc, buf, insn->size); insn->exec(ch, buf[0], &buf[1], insn->size - 1); } @@ -1186,7 +1189,7 @@ static int pl330_exec_cycle(PL330Chan *channel) if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) { int len = q->len - (q->addr & (q->len - 1)); - dma_memory_read(&address_space_memory, q->addr, buf, len); + dma_memory_read(s->mem_as, q->addr, buf, len); trace_pl330_exec_cycle(q->addr, len); if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) { pl330_hexdump(buf, len); @@ -1217,7 +1220,7 @@ static int pl330_exec_cycle(PL330Chan *channel) fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag); } if (fifo_res == PL330_FIFO_OK || q->z) { - dma_memory_write(&address_space_memory, q->addr, buf, len); + dma_memory_write(s->mem_as, q->addr, buf, len); trace_pl330_exec_cycle(q->addr, len); if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) { pl330_hexdump(buf, len); @@ -1562,6 +1565,18 @@ static void pl330_realize(DeviceState *dev, Error **errp) "dma", PL330_IOMEM_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + if (!s->mem_mr) { + error_setg(errp, "'memory' link is not set"); + return; + } else if (s->mem_mr == get_system_memory()) { + /* Avoid creating new AS for system memory. */ + s->mem_as = &address_space_memory; + } else { + s->mem_as = g_new0(AddressSpace, 1); + address_space_init(s->mem_as, s->mem_mr, + memory_region_name(s->mem_mr)); + } + s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl330_exec_cycle_timer, s); s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) | @@ -1656,6 +1671,9 @@ static Property pl330_properties[] = { DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16), DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256), + DEFINE_PROP_LINK("memory", PL330State, mem_mr, + TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_END_OF_LIST(), }; |