From 010f9a472c8c762a727d72310f55db3258cda3d5 Mon Sep 17 00:00:00 2001 From: Jamin Lin Date: Thu, 15 May 2025 16:09:35 +0800 Subject: [PATCH] hw/misc/aspeed_hace: Ensure HASH_IRQ is always set to prevent firmware hang MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Currently, if the program encounters an unsupported algorithm, it does not set the HASH_IRQ bit in the status register and send an interrupt to indicate command completion. As a result, the FW gets stuck waiting for a completion signal from the HACE module. Additionally, in do_hash_operation, if an error occurs within the conditional statement, the HASH_IRQ bit is not set in the status register. This causes the firmware to continuously send HASH commands, as it is unaware that the HACE model has completed processing the command. To fix this, the HASH_IRQ bit in the status register must always be set to ensure that the firmware receives an interrupt from the HACE module, preventing it from getting stuck or repeatedly sending HASH commands. Signed-off-by: Jamin Lin Fixes: c5475b3 ("hw: Model ASPEED's Hash and Crypto Engine") Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/qemu-devel/20250515081008.583578-4-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater (cherry picked from commit fb8e59abbe46957cd599bb9aa9221fad1e4e989e) Signed-off-by: Michael Tokarev --- hw/misc/aspeed_hace.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c index 11bd25708e..20f645f49b 100644 --- a/hw/misc/aspeed_hace.c +++ b/hw/misc/aspeed_hace.c @@ -278,12 +278,6 @@ static void do_hash_operation(AspeedHACEState *s, int algo, bool sg_mode, iov[i - 1].iov_len, false, iov[i - 1].iov_len); } - - /* - * Set status bits to indicate completion. Testing shows hardware sets - * these irrespective of HASH_IRQ_EN. - */ - s->regs[R_STATUS] |= HASH_IRQ; } static uint64_t aspeed_hace_read(void *opaque, hwaddr addr, unsigned int size) @@ -358,10 +352,16 @@ static void aspeed_hace_write(void *opaque, hwaddr addr, uint64_t data, qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid hash algorithm selection 0x%"PRIx64"\n", __func__, data & ahc->hash_mask); - break; + } else { + do_hash_operation(s, algo, data & HASH_SG_EN, + ((data & HASH_HMAC_MASK) == HASH_DIGEST_ACCUM)); } - do_hash_operation(s, algo, data & HASH_SG_EN, - ((data & HASH_HMAC_MASK) == HASH_DIGEST_ACCUM)); + + /* + * Set status bits to indicate completion. Testing shows hardware sets + * these irrespective of HASH_IRQ_EN. + */ + s->regs[R_STATUS] |= HASH_IRQ; if (data & HASH_IRQ_EN) { qemu_irq_raise(s->irq); -- 2.39.5