All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@oss.qualcomm.com>
To: qemu-devel@nongnu.org
Subject: [PULL 02/51] hw/sd: sdhci: Fix SDMA boundary bug
Date: Thu,  3 Sep 2026 12:38:46 +0200	[thread overview]
Message-ID: <20260903103936.62355-3-philmd@oss.qualcomm.com> (raw)
In-Reply-To: <20260903103936.62355-1-philmd@oss.qualcomm.com>

From: Tao Ding <dingtao0430@163.com>

During SDMA transfers, the controller raises an interrupt at buffer boundaries
to request a system address update. The host driver will rewrite the SDHC_SYSAD register.
(according to PartA2_SD_Host_Controller_Simplified_Specification_Ver2.00.pdf section 2.2.1)
However, the current code will ignore write operations to SDHC_SYSAD.

To fix this bug, when SDMA encounters a boundary, a state is set to record it.
In this state, SDHC_SYSAD can be written. In other cases, it is still protected by TRANSFERRING_DATA.

Meanwhile, a subsection has been added for migration.

Suggested-by: Bin Meng <bmeng.cn@gmail.com>
Signed-off-by: Tao Ding <dingtao0430@163.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Message-ID: <20260715160731.29969-2-dingtao0430@163.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
---
 include/hw/sd/sdhci.h |  2 ++
 hw/sd/sdhci.c         | 54 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
index a9da6203fcb..c485277744e 100644
--- a/include/hw/sd/sdhci.h
+++ b/include/hw/sd/sdhci.h
@@ -103,6 +103,8 @@ struct SDHCIState {
      * to be protected. Set wp_inverted to invert the signal.
      */
     bool wp_inverted;
+    /* Indicate that SDMA transfer is paused due to hitting the boundary */
+    bool sdma_boundary_paused;
 };
 typedef struct SDHCIState SDHCIState;
 
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index e58a6103970..02f09187272 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -307,6 +307,7 @@ static void sdhci_reset(SDHCIState *s)
     s->data_count = 0;
     s->stopped_state = sdhc_not_stopped;
     s->pending_insert_state = false;
+    s->sdma_boundary_paused = false;
     if (object_dynamic_cast(OBJECT(s), TYPE_FSL_ESDHC_BE) ||
             object_dynamic_cast(OBJECT(s), TYPE_FSL_ESDHC_LE)) {
         s->norintstsen = 0x013f;
@@ -414,6 +415,7 @@ static void sdhci_end_transfer(SDHCIState *s)
         s->norintsts |= SDHC_NIS_TRSCMP;
     }
 
+    s->sdma_boundary_paused = false;
     sdhci_update_irq(s);
 }
 
@@ -681,6 +683,7 @@ static void sdhci_sdma_transfer_multi_blocks(SDHCIState *s)
     if (s->blkcnt == 0) {
         sdhci_end_transfer(s);
     } else {
+        s->sdma_boundary_paused = true;
         sdhci_update_irq(s);
     }
 }
@@ -717,6 +720,15 @@ static void sdhci_sdma_transfer(SDHCIState *s)
     }
 }
 
+static bool sdhci_sdma_transfer_active(SDHCIState *s)
+{
+    return TRANSFERRING_DATA(s->prnsts) &&
+            (s->trnmod & SDHC_TRNS_DMA) &&
+            s->blkcnt &&
+            (s->blksize & BLOCK_SIZE_MASK) &&
+            SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA;
+}
+
 typedef struct ADMADescr {
     hwaddr addr;
     uint16_t length;
@@ -1164,6 +1176,7 @@ static inline void sdhci_reset_write(SDHCIState *s, uint8_t value)
                 SDHC_DATA_INHIBIT | SDHC_DAT_LINE_ACTIVE);
         s->blkgap &= ~(SDHC_STOP_AT_GAP_REQ | SDHC_CONTINUE_REQ);
         s->stopped_state = sdhc_not_stopped;
+        s->sdma_boundary_paused = false;
         s->norintsts &= ~(SDHC_NIS_WBUFRDY | SDHC_NIS_RBUFRDY |
                 SDHC_NIS_DMA | SDHC_NIS_TRSCMP | SDHC_NIS_BLKGAP);
         break;
@@ -1185,7 +1198,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
 
     switch (offset & ~0x3) {
     case SDHC_SYSAD:
-        if (!TRANSFERRING_DATA(s->prnsts)) {
+        if (!TRANSFERRING_DATA(s->prnsts) || s->sdma_boundary_paused) {
             s->sdmasysad = (s->sdmasysad & mask) | value;
             MASKED_WRITE(s->sdmasysad, mask, value);
             /* Writing to last byte of sdmasysad might trigger transfer */
@@ -1464,6 +1477,31 @@ static bool sdhci_pending_insert_vmstate_needed(void *opaque)
     return s->pending_insert_state;
 }
 
+static bool sdhci_sdma_boundary_paused_vmstate_needed(void *opaque)
+{
+    SDHCIState *s = opaque;
+
+    return s->sdma_boundary_paused;
+}
+
+static int sdhci_pre_load(void *opaque)
+{
+    SDHCIState *s = opaque;
+
+    s->sdma_boundary_paused = false;
+    return 0;
+}
+
+static int sdhci_post_load(void *opaque, int version_id)
+{
+    SDHCIState *s = opaque;
+
+    if (!s->sdma_boundary_paused) {
+        s->sdma_boundary_paused = sdhci_sdma_transfer_active(s);
+    }
+    return 0;
+}
+
 static const VMStateDescription sdhci_pending_insert_vmstate = {
     .name = "sdhci/pending-insert",
     .version_id = 1,
@@ -1475,10 +1513,23 @@ static const VMStateDescription sdhci_pending_insert_vmstate = {
     },
 };
 
+static const VMStateDescription sdhci_sdma_boundary_paused_vmstate = {
+    .name = "sdhci/sdma_boundary_paused",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .needed = sdhci_sdma_boundary_paused_vmstate_needed,
+    .fields = (const VMStateField[]) {
+        VMSTATE_BOOL(sdma_boundary_paused, SDHCIState),
+        VMSTATE_END_OF_LIST()
+    },
+};
+
 const VMStateDescription sdhci_vmstate = {
     .name = "sdhci",
     .version_id = 1,
     .minimum_version_id = 1,
+    .pre_load = sdhci_pre_load,
+    .post_load = sdhci_post_load,
     .fields = (const VMStateField[]) {
         VMSTATE_UINT32(sdmasysad, SDHCIState),
         VMSTATE_UINT16(blksize, SDHCIState),
@@ -1512,6 +1563,7 @@ const VMStateDescription sdhci_vmstate = {
     },
     .subsections = (const VMStateDescription * const []) {
         &sdhci_pending_insert_vmstate,
+        &sdhci_sdma_boundary_paused_vmstate,
         NULL
     },
 };
-- 
2.53.0



  parent reply	other threads:[~2026-09-03 10:40 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03 10:38 [PULL 00/51] Misc HW/accel patches for 2026-09-03 Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 01/51] hw/sd: give the RPMB vmstate subsection a name of its own Philippe Mathieu-Daudé
2026-09-03 10:38 ` Philippe Mathieu-Daudé [this message]
2026-09-03 10:38 ` [PULL 03/51] qtest: add xilinx-zynq SDHCI sdma test Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 04/51] hw/sd: sdhci: Migrate the Host Control 2 register Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 05/51] hw/sd: sdhci: Accept version 4 enable without UHS-I Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 06/51] hw/sd: sdhci: Factor sdhci_advance_sdma_address() helper out Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 07/51] hw/sd: sdhci: Factor sdhci_sdma_address() " Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 08/51] hw/sd: sdhci: Use version 4 system address for SDMA Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 09/51] hw/sd: sdhci: Support version 4 ADMA 64-bit addressing Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 10/51] hw/sd: sdhci: Resume version 4 SDMA at buffer boundaries Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 11/51] hw/sd/sdcard: Register device ops in drives without media Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 12/51] hw/cxl: fix timer leak in cxl_destroy_cci() Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 13/51] hw/sd/axiado_sdhci: Add header guard Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 14/51] MAINTAINERS: Cover pflash QTest in pflash section Philippe Mathieu-Daudé
2026-09-03 10:38 ` [PULL 15/51] hw/block/pflash_cfi01: Always set romd mode when clearing wcycle and cmd Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 16/51] hw/block/pflash_cfi02: Add migration support Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 17/51] accel/tcg: Rename for exception codes named @ret as @excp Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 18/51] accel/tcg: Restrict EXCP_HALTED handling to system emulation Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 19/51] accel/tcg: Check %halted field in cpu_handle_halt() caller Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 20/51] target/i386: Remove const qualifier in ptw_setl*() Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 21/51] linux-user: Uncast void pointer argument as Object in target_cpu_free() Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 22/51] cpus: Add const-qualified CPU environment accessors Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 23/51] linux-user: Replace env_cpu_const() by generic env_cpu() equivalent Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 24/51] system/cpus: Constify various CPUState arguments Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 25/51] target/avr: Constify CPUAVRState for some cpu_*() getters Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 26/51] target/hexagon: Constify CPUHexagonState in hexagon_thread_is_enabled() Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 27/51] target/i386: Constify CPU*State for cpu_*_interrupt() getters Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 28/51] target/loongarch: Constify LoongArchTLB Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 29/51] target/mips: Constify CPUMIPSState for various cpu_*() getters Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 30/51] target/s390x: Constify S390CPU for cpu_has_*() getters Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 31/51] target/riscv: Constify @iprio argument in riscv_cpu_pending_to_irq() Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 32/51] target/sparc: Constify CPUSPARCState for various cpu_*() getters Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 33/51] target/tricore: Document architectural interrupts as not implemented Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 34/51] target/xtensa: Constify CPUXtensaState in xtensa_replicate_windowstart() Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 35/51] target/arm: Return immediately on error in kvm_arch_init() Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 36/51] qom/object: add is_available callback to TypeInfo Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 37/51] hw/arm: filter minimal set of machines Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 38/51] system: query machines using TYPE_MACHINE Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 39/51] target-info: remove machine_typename Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 40/51] hw/arm: remove TYPE_TARGET_{AARCH64,ARM}_MACHINE Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 41/51] hw/arm: remove {arm, arm_aarch64, aarch64}_machine_interfaces Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 42/51] hw/arm: remove DEFINE_MACHINE_{AARCH64,ARM} Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 43/51] hw/arm: remove machines-qom.h Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 44/51] hw/riscv: remove TYPE_TARGET_{RISCV32,RISCV64}_MACHINE Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 45/51] hw/riscv: remove {riscv32, riscv32_64, riscv64}_machine_interfaces Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 46/51] hw/riscv: remove DEFINE_MACHINE_{RISCV32,RISCV64} Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 47/51] hw/riscv: remove machines-qom.h Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 48/51] rustfmt: disable wrap_comments Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 49/51] system: improve -mon deprecation warning Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 50/51] MAINTAINERS: Stop reviewing meson-related patches Philippe Mathieu-Daudé
2026-09-03 10:39 ` [PULL 51/51] MAINTAINERS: Update PhilMD's email address Philippe Mathieu-Daudé
2026-09-03 19:15 ` [PULL 00/51] Misc HW/accel patches for 2026-09-03 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260903103936.62355-3-philmd@oss.qualcomm.com \
    --to=philmd@oss.qualcomm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.