All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 0/4] sd: sdhci: correct transfer mode register usage
@ 2017-02-11 15:06 P J P
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer P J P
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: P J P @ 2017-02-11 15:06 UTC (permalink / raw)
  To: Qemu Developers
  Cc: Alistair Francis, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

From: Prasad J Pandit <pjp@fedoraproject.org>

Hello,

In SDHCI protocol, the 'Block Count Enable' bit of the Transfer Mode
register is used to control 's->blkcnt' value. This bit is not relevant
in single block transfers. Also, Transfer Mode register value could be
set such that 's->blkcnt' would not see an update during multi block
transfers. Thus leading to an infinite loop.

This patch set attempts to correct 'Block Count Enable' bit usage.

This series incorporates changes suggested in patch set v2:
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg01608.html

Thank you.
--
Prasad J Pandit (4):
  sd: sdhci: check transfer mode register in multi block transfer
  sd: sdhci: mask transfer mode register value
  sd: sdhci: conditionally invoke multi block transfer
  sd: sdhci: Remove block count enable check in single block transfers

 hw/sd/sdhci.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

-- 
2.9.3

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer
  2017-02-11 15:06 [Qemu-devel] [PATCH v3 0/4] sd: sdhci: correct transfer mode register usage P J P
@ 2017-02-11 15:06 ` P J P
  2017-02-13 19:55   ` Alistair Francis
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value P J P
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: P J P @ 2017-02-11 15:06 UTC (permalink / raw)
  To: Qemu Developers
  Cc: Alistair Francis, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

From: Prasad J Pandit <pjp@fedoraproject.org>

In the SDHCI protocol, 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 <wjjzhang@tencent.com>
Reported-by: Jiang Xin <jiangxin1@huawei.com>
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
---
 hw/sd/sdhci.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

Update: use qemu_log_mask(LOG_UNIMP, ...)
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02354.html

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 5bd5ab6..a9c744b 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) {
+        qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
+        return;
+    }
+
     /* 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 {
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value
  2017-02-11 15:06 [Qemu-devel] [PATCH v3 0/4] sd: sdhci: correct transfer mode register usage P J P
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer P J P
@ 2017-02-11 15:06 ` P J P
  2017-02-13 19:52   ` Alistair Francis
  2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 3/4] sd: sdhci: conditionally invoke multi block transfer P J P
  2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 4/4] sd: sdhci: Remove block count enable check in single block transfers P J P
  3 siblings, 1 reply; 9+ messages in thread
From: P J P @ 2017-02-11 15:06 UTC (permalink / raw)
  To: Qemu Developers
  Cc: Alistair Francis, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

From: Prasad J Pandit <pjp@fedoraproject.org>

In SDHCI protocol, the transfer mode register is defined
to be of 6 bits. Mask its value with '0x0037' so that an
invalid value couldn't be assigned.

Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
---
 hw/sd/sdhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Update: mask s->trnmod register value
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02354.html

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index a9c744b..0307b8c 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -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);
         MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
 
         /* Writing to the upper byte of CMDREG triggers SD command generation */
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH v3 3/4] sd: sdhci: conditionally invoke multi block transfer
  2017-02-11 15:06 [Qemu-devel] [PATCH v3 0/4] sd: sdhci: correct transfer mode register usage P J P
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer P J P
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value P J P
@ 2017-02-11 15:07 ` P J P
  2017-02-13 19:55   ` Alistair Francis
  2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 4/4] sd: sdhci: Remove block count enable check in single block transfers P J P
  3 siblings, 1 reply; 9+ messages in thread
From: P J P @ 2017-02-11 15:07 UTC (permalink / raw)
  To: Qemu Developers
  Cc: Alistair Francis, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

From: Prasad J Pandit <pjp@fedoraproject.org>

In sdhci_write invoke multi block transfer if it is enabled
in the transfer mode register 's->trnmod'.

Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
---
 hw/sd/sdhci.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Update: test if (s->trnmod & SDHC_TRNS_MULTI) is true
  -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02357.html

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 0307b8c..99fa0c7 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1022,7 +1022,11 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
         /* Writing to last byte of sdmasysad might trigger transfer */
         if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
                 s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
-            sdhci_sdma_transfer_multi_blocks(s);
+            if (s->trnmod & SDHC_TRNS_MULTI) {
+                sdhci_sdma_transfer_multi_blocks(s);
+            } else {
+                sdhci_sdma_transfer_single_block(s);
+            }
         }
         break;
     case SDHC_BLKSIZE:
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Qemu-devel] [PATCH v3 4/4] sd: sdhci: Remove block count enable check in single block transfers
  2017-02-11 15:06 [Qemu-devel] [PATCH v3 0/4] sd: sdhci: correct transfer mode register usage P J P
                   ` (2 preceding siblings ...)
  2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 3/4] sd: sdhci: conditionally invoke multi block transfer P J P
@ 2017-02-11 15:07 ` P J P
  3 siblings, 0 replies; 9+ messages in thread
From: P J P @ 2017-02-11 15:07 UTC (permalink / raw)
  To: Qemu Developers
  Cc: Alistair Francis, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

From: Prasad J Pandit <pjp@fedoraproject.org>

In SDHCI protocol, the 'Block count enable' bit of the Transfer
Mode register is relevant only in multi block transfers. We need
not check it in single block transfers.

Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
---
 hw/sd/sdhci.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 99fa0c7..d612a80 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -569,7 +569,6 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
 }
 
 /* single block SDMA transfer */
-
 static void sdhci_sdma_transfer_single_block(SDHCIState *s)
 {
     int n;
@@ -588,10 +587,7 @@ static void sdhci_sdma_transfer_single_block(SDHCIState *s)
             sdbus_write_data(&s->sdbus, s->fifo_buffer[n]);
         }
     }
-
-    if (s->trnmod & SDHC_TRNS_BLK_CNT_EN) {
-        s->blkcnt--;
-    }
+    s->blkcnt--;
 
     sdhci_end_transfer(s);
 }
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value P J P
@ 2017-02-13 19:52   ` Alistair Francis
  2017-02-14  6:23     ` P J P
  0 siblings, 1 reply; 9+ messages in thread
From: Alistair Francis @ 2017-02-13 19:52 UTC (permalink / raw)
  To: P J P
  Cc: Qemu Developers, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

On Sat, Feb 11, 2017 at 7:06 AM, P J P <ppandit@redhat.com> wrote:
> From: Prasad J Pandit <pjp@fedoraproject.org>
>
> In SDHCI protocol, the transfer mode register is defined
> to be of 6 bits. Mask its value with '0x0037' so that an
> invalid value couldn't be assigned.
>
> Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
> ---
>  hw/sd/sdhci.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> Update: mask s->trnmod register value
>   -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02354.html
>
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index a9c744b..0307b8c 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -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);

This looks good.

Can you use a macro for the value so then it is explained and easier
to change in the future?

Once you have done that:

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

>          MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16);
>
>          /* Writing to the upper byte of CMDREG triggers SD command generation */
> --
> 2.9.3
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH v3 3/4] sd: sdhci: conditionally invoke multi block transfer
  2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 3/4] sd: sdhci: conditionally invoke multi block transfer P J P
@ 2017-02-13 19:55   ` Alistair Francis
  0 siblings, 0 replies; 9+ messages in thread
From: Alistair Francis @ 2017-02-13 19:55 UTC (permalink / raw)
  To: P J P
  Cc: Qemu Developers, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

On Sat, Feb 11, 2017 at 7:07 AM, P J P <ppandit@redhat.com> wrote:
> From: Prasad J Pandit <pjp@fedoraproject.org>
>
> In sdhci_write invoke multi block transfer if it is enabled
> in the transfer mode register 's->trnmod'.
>
> Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  hw/sd/sdhci.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> Update: test if (s->trnmod & SDHC_TRNS_MULTI) is true
>   -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02357.html
>
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 0307b8c..99fa0c7 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1022,7 +1022,11 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
>          /* Writing to last byte of sdmasysad might trigger transfer */
>          if (!(mask & 0xFF000000) && TRANSFERRING_DATA(s->prnsts) && s->blkcnt &&
>                  s->blksize && SDHC_DMA_TYPE(s->hostctl) == SDHC_CTRL_SDMA) {
> -            sdhci_sdma_transfer_multi_blocks(s);
> +            if (s->trnmod & SDHC_TRNS_MULTI) {
> +                sdhci_sdma_transfer_multi_blocks(s);
> +            } else {
> +                sdhci_sdma_transfer_single_block(s);
> +            }
>          }
>          break;
>      case SDHC_BLKSIZE:
> --
> 2.9.3
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer
  2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer P J P
@ 2017-02-13 19:55   ` Alistair Francis
  0 siblings, 0 replies; 9+ messages in thread
From: Alistair Francis @ 2017-02-13 19:55 UTC (permalink / raw)
  To: P J P
  Cc: Qemu Developers, Peter Maydell, Wjjzhang, Jiang Xin, Prasad J Pandit

On Sat, Feb 11, 2017 at 7:06 AM, P J P <ppandit@redhat.com> wrote:
> From: Prasad J Pandit <pjp@fedoraproject.org>
>
> In the SDHCI protocol, 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 <wjjzhang@tencent.com>
> Reported-by: Jiang Xin <jiangxin1@huawei.com>
> Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>

Reviewed-by: Alistair Francis <alistair.francis@xilinx.com>

Thanks,

Alistair

> ---
>  hw/sd/sdhci.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> Update: use qemu_log_mask(LOG_UNIMP, ...)
>   -> https://lists.gnu.org/archive/html/qemu-devel/2017-02/msg02354.html
>
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index 5bd5ab6..a9c744b 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) {
> +        qemu_log_mask(LOG_UNIMP, "infinite transfer is not supported\n");
> +        return;
> +    }
> +
>      /* 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 {
> --
> 2.9.3
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value
  2017-02-13 19:52   ` Alistair Francis
@ 2017-02-14  6:23     ` P J P
  0 siblings, 0 replies; 9+ messages in thread
From: P J P @ 2017-02-14  6:23 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Qemu Developers, Peter Maydell, Wjjzhang, Jiang Xin

+-- On Mon, 13 Feb 2017, Alistair Francis wrote --+
| > -        MASKED_WRITE(s->trnmod, mask, value);
| > +        MASKED_WRITE(s->trnmod, mask, value & 0x0037);
| 
| This looks good.
| 
| Can you use a macro for the value so then it is explained and easier
| to change in the future?

  Done, sent patch v4.

Thank you.
--
Prasad J Pandit / Red Hat Product Security Team
47AF CE69 3A90 54AA 9045 1053 DD13 3D32 FE5B 041F

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-02-14  6:23 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-11 15:06 [Qemu-devel] [PATCH v3 0/4] sd: sdhci: correct transfer mode register usage P J P
2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 1/4] sd: sdhci: check transfer mode register in multi block transfer P J P
2017-02-13 19:55   ` Alistair Francis
2017-02-11 15:06 ` [Qemu-devel] [PATCH v3 2/4] sd: sdhci: mask transfer mode register value P J P
2017-02-13 19:52   ` Alistair Francis
2017-02-14  6:23     ` P J P
2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 3/4] sd: sdhci: conditionally invoke multi block transfer P J P
2017-02-13 19:55   ` Alistair Francis
2017-02-11 15:07 ` [Qemu-devel] [PATCH v3 4/4] sd: sdhci: Remove block count enable check in single block transfers P J P

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.