On Tue, Feb 7, 2017 at 10:42 PM, P J P <ppan...@redhat.com> wrote: > From: Prasad J Pandit <p...@fedoraproject.org> > > In SDHCI device emulation the transfer mode register value > is used during multi block transfer to check if block count > register is enabled and should be updated. Transfer mode > register could be set such that, block count register would > not be updated, thus leading to an infinite loop. Add check > to avoid it. > > Reported-by: Wjjzhang <wjjzh...@tencent.com> > Reported-by: Jiang Xin <jiangx...@huawei.com> > Signed-off-by: Prasad J Pandit <p...@fedoraproject.org> > --- > hw/sd/sdhci.c | 12 ++++++------ > 1 file changed, 6 insertions(+), 6 deletions(-) > > Update per: print an error message before return > -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg01567.html > > diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c > index 5bd5ab6..cf400c8 100644 > --- a/hw/sd/sdhci.c > +++ b/hw/sd/sdhci.c > @@ -486,6 +486,11 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState > *s) > uint32_t boundary_chk = 1 << (((s->blksize & 0xf000) >> 12) + 12); > uint32_t boundary_count = boundary_chk - (s->sdmasysad % boundary_chk); > > + if (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || !s->blkcnt) { > + ERRPRINT("Infinite transfers are not supported\n"); > + return; > + }
You should use the qemu_log_mask() function. It'll look something like this: qemu_log_mask(LOG_UNIMP, .... > + > /* XXX: Some sd/mmc drivers (for example, u-boot-slp) do not account for > * possible stop at page boundary if initial address is not page aligned, > * allow them to work properly */ > @@ -797,11 +802,6 @@ static void sdhci_data_transfer(void *opaque) > if (s->trnmod & SDHC_TRNS_DMA) { > switch (SDHC_DMA_TYPE(s->hostctl)) { > case SDHC_CTRL_SDMA: > - if ((s->trnmod & SDHC_TRNS_MULTI) && > - (!(s->trnmod & SDHC_TRNS_BLK_CNT_EN) || s->blkcnt == 0)) > { > - break; > - } > - > if ((s->blkcnt == 1) || !(s->trnmod & SDHC_TRNS_MULTI)) { > sdhci_sdma_transfer_single_block(s); > } else { > @@ -1050,7 +1050,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, > unsigned size) > if (!(s->capareg & SDHC_CAN_DO_DMA)) { > value &= ~SDHC_TRNS_DMA; > } > - MASKED_WRITE(s->trnmod, mask, value); > + MASKED_WRITE(s->trnmod, mask, value & 0x0037); Maybe this is worth being in a separate patch with an explanation. Thanks, Alistair > MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); > > /* Writing to the upper byte of CMDREG triggers SD command > generation */ > -- > 2.9.3 >