From patchwork Tue Sep 17 18:08:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Michael Tokarev X-Patchwork-Id: 13806391 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3269ECAC594 for ; Tue, 17 Sep 2024 18:10:00 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sqcdc-00050d-3D; Tue, 17 Sep 2024 14:09:21 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sqcdP-0004Zp-Pb; Tue, 17 Sep 2024 14:09:07 -0400 Received: from isrv.corpit.ru ([86.62.121.231]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sqcdN-0002OI-Uk; Tue, 17 Sep 2024 14:09:07 -0400 Received: from tsrv.corpit.ru (tsrv.tls.msk.ru [192.168.177.2]) by isrv.corpit.ru (Postfix) with ESMTP id 063E38FBC7; Tue, 17 Sep 2024 21:08:30 +0300 (MSK) Received: from think4mjt.tls.msk.ru (mjtthink.wg.tls.msk.ru [192.168.177.146]) by tsrv.corpit.ru (Postfix) with ESMTP id 85BF113E749; Tue, 17 Sep 2024 21:08:45 +0300 (MSK) From: Michael Tokarev To: qemu-devel@nongnu.org Cc: qemu-stable@nongnu.org, =?utf-8?q?Jan_Kl=C3=B6tzke?= , Peter Maydell , Michael Tokarev Subject: [Stable-7.2.14 47/47] hw/intc/arm_gic: fix spurious level triggered interrupts Date: Tue, 17 Sep 2024 21:08:36 +0300 Message-Id: <20240917180836.633380-8-mjt@tls.msk.ru> X-Mailer: git-send-email 2.39.5 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=86.62.121.231; envelope-from=mjt@tls.msk.ru; helo=isrv.corpit.ru X-Spam_score_int: -68 X-Spam_score: -6.9 X-Spam_bar: ------ X-Spam_report: (-6.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_HI=-5, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Jan Klötzke On GICv2 and later, level triggered interrupts are pending when either the interrupt line is asserted or the interrupt was made pending by a GICD_ISPENDRn write. Making a level triggered interrupt pending by software persists until either the interrupt is acknowledged or cleared by writing GICD_ICPENDRn. As long as the interrupt line is asserted, the interrupt is pending in any case. This logic is transparently implemented in gic_test_pending() for GICv1 and GICv2. The function combines the "pending" irq_state flag (used for edge triggered interrupts and software requests) and the line status (tracked in the "level" field). However, we also incorrectly set the pending flag on a guest write to GICD_ISENABLERn if the line of a level triggered interrupt was asserted. This keeps the interrupt pending even if the line is de-asserted after some time. This incorrect logic is a leftover of the initial 11MPCore GIC implementation. That handles things slightly differently to the architected GICv1 and GICv2. The 11MPCore TRM does not give a lot of detail on the corner cases of its GIC's behaviour, and historically we have not wanted to investigate exactly what it does in reality, so QEMU's GIC model takes the approach of "retain our existing behaviour for 11MPCore, and implement the architectural standard for later GIC revisions". On that basis, commit 8d999995e45c10 in 2013 is where we added the "level-triggered interrupt with the line asserted" handling to gic_test_pending(), and we deliberately kept the old behaviour of gic_test_pending() for REV_11MPCORE. That commit should have added the "only if 11MPCore" condition to the setting of the pending bit on writes to GICD_ISENABLERn, but forgot it. Add the missing "if REV_11MPCORE" condition, so that our behaviour on GICv1 and GICv2 matches the GIC architecture requirements. Cc: qemu-stable@nongnu.org Fixes: 8d999995e45c10 ("arm_gic: Fix GIC pending behavior") Signed-off-by: Jan Klötzke Message-id: 20240911114826.3558302-1-jan.kloetzke@kernkonzept.com Reviewed-by: Peter Maydell [PMM: expanded comment a little and converted to coding-style form; expanded commit message with the historical backstory] Signed-off-by: Peter Maydell (cherry picked from commit 110684c9a69a02cbabfbddcd3afa921826ad565c) Signed-off-by: Michael Tokarev diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 47f01e45e3..b8a4364b7f 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -1263,9 +1263,14 @@ static void gic_dist_writeb(void *opaque, hwaddr offset, trace_gic_enable_irq(irq + i); } GIC_DIST_SET_ENABLED(irq + i, cm); - /* If a raised level triggered IRQ enabled then mark - is as pending. */ - if (GIC_DIST_TEST_LEVEL(irq + i, mask) + /* + * If a raised level triggered IRQ enabled then mark + * it as pending on 11MPCore. For other GIC revisions we + * handle the "level triggered and line asserted" check + * at the other end in gic_test_pending(). + */ + if (s->revision == REV_11MPCORE + && GIC_DIST_TEST_LEVEL(irq + i, mask) && !GIC_DIST_TEST_EDGE_TRIGGER(irq + i)) { DPRINTF("Set %d pending mask %x\n", irq + i, mask); GIC_DIST_SET_PENDING(irq + i, mask);