From: Shameer Kolothum <[email protected]>
When a guest hits a command error, the hardware sets GERROR and the guest
acknowledges it by writing GERRORN to match. These registers use toggle
semantics, and since GERROR is read-only, both GERROR and GERRORN may
remain set after an error has been handled. As long as they stay equal
there is no pending error, so a subsequent VM is unaffected.
When a new VM starts, QEMU allocates the hardware VCMDQ and flushes its
cached GERRORN of zero, while the hardware may still have both GERROR and
GERRORN set from an error the previous guest acknowledged. This makes them
differ again, so the hardware sees a pending error and stall the VCMDQ,
leading to CMD_SYNC timeouts.
Do not sync GERRORN when allocating a hardware VCMDQ.
Fixes: 1d0f77535417 ("hw/arm/tegra241-cmdqv: Route allocated VCMDQ Page0
accesses to the mmap'd host VINTF page0")
Suggested-by: Nicolin Chen <[email protected]>
Signed-off-by: Shameer Kolothum <[email protected]>
Reviewed-by: Nicolin Chen <[email protected]>
Tested-by: Nicolin Chen <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
Message-id: [email protected]
Signed-off-by: Peter Maydell <[email protected]>
---
hw/arm/tegra241-cmdqv.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c
index 7223aa9d1d9..273633e6293 100644
--- a/hw/arm/tegra241-cmdqv.c
+++ b/hw/arm/tegra241-cmdqv.c
@@ -212,7 +212,9 @@ static inline uint32_t
*tegra241_cmdqv_vintf_lvcmdq_ptr(Tegra241CMDQV *cmdqv,
/*
* Flush cached register writes into the mmap'd host VINTF page0 after a
* successful HW_QUEUE_ALLOC, so the guest's earlier writes survive
- * the cache-to-hardware transition.
+ * the cache-to-hardware transition. GERRORN is intentionally not synced,
+ * as overwriting it with the cached value could recreate a GERROR != GERRORN
+ * mismatch and stall the VCMDQ.
*/
static void tegra241_cmdqv_sync_vcmdq(Tegra241CMDQV *cmdqv, int index)
{
@@ -229,9 +231,6 @@ static void tegra241_cmdqv_sync_vcmdq(Tegra241CMDQV *cmdqv,
int index)
ptr = tegra241_cmdqv_vintf_lvcmdq_ptr(cmdqv, index, A_VCMDQ0_CONFIG);
*ptr = cmdqv->vcmdq_config[index];
-
- ptr = tegra241_cmdqv_vintf_lvcmdq_ptr(cmdqv, index, A_VCMDQ0_GERRORN);
- *ptr = cmdqv->vcmdq_gerrorn[index];
}
/*
--
2.43.0