[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[RFC 2/2] hw/ppc/ppc440_uc: Handle mapping failure in DMA engine
From: |
Peter Maydell |
Subject: |
[RFC 2/2] hw/ppc/ppc440_uc: Handle mapping failure in DMA engine |
Date: |
Tue, 26 Jul 2022 19:23:41 +0100 |
Currently the code for doing DMA in dcr_write_dma() has no fallback
code for if its calls to cpu_physical_memory_map() fail. Add
handling for this situation, by using address_space_read() and
address_space_write() to do the data transfers.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
I believe this to be equivalent to the fastpath code. However, as
the comments note, I don't know what the intended behaviour on a DMA
memory access error is, because I couldn't find a datasheet for this
hardware. I am also a bit suspicious that the current code does not
seem to update any of the count, source or destination addresses
after the memory transfer: is that really how the hardware behaves?
---
hw/ppc/ppc440_uc.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index 11fdb88c220..0879f180a14 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -905,6 +905,7 @@ static void dcr_write_dma(void *opaque, int dcrn, uint32_t
val)
uint8_t *rptr, *wptr;
hwaddr rlen, wlen;
hwaddr xferlen;
+ bool fastpathed = false;
sidx = didx = 0;
width = 1 << ((val & DMA0_CR_PW) >> 25);
@@ -915,6 +916,7 @@ static void dcr_write_dma(void *opaque, int dcrn, uint32_t
val)
wptr = cpu_physical_memory_map(dma->ch[chnl].da, &wlen,
true);
if (rptr && rlen == xferlen && wptr && wlen == xferlen) {
+ fastpathed = true;
if (!(val & DMA0_CR_DEC) &&
val & DMA0_CR_SAI && val & DMA0_CR_DAI) {
/* optimise common case */
@@ -940,6 +942,33 @@ static void dcr_write_dma(void *opaque, int dcrn, uint32_t
val)
if (rptr) {
cpu_physical_memory_unmap(rptr, rlen, 0, sidx);
}
+ if (!fastpathed) {
+ /* Fast-path failed, do each access one at a time */
+ for (sidx = didx = i = 0; i < count; i++) {
+ uint8_t buf[8];
+ assert(width <= sizeof(buf));
+ if (address_space_read(&address_space_memory,
+ dma->ch[chnl].sa + sidx,
+ MEMTXATTRS_UNSPECIFIED,
+ buf, width) != MEMTX_OK) {
+ /* FIXME: model correct behaviour on errors */
+ break;
+ }
+ if (address_space_write(&address_space_memory,
+ dma->ch[chnl].da + didx,
+ MEMTXATTRS_UNSPECIFIED,
+ buf, width) != MEMTX_OK) {
+ /* FIXME: model correct behaviour on errors */
+ break;
+ }
+ if (val & DMA0_CR_SAI) {
+ sidx += width;
+ }
+ if (val & DMA0_CR_DAI) {
+ didx += width;
+ }
+ }
+ }
}
}
break;
--
2.25.1
Re: [RFC 0/2] Fix Coverity and other errors in ppc440_uc DMA, BALATON Zoltan, 2022/07/28