From nobody Sat May 30 19:24:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=163.com ARC-Seal: i=1; a=rsa-sha256; t=1777383400; cv=none; d=zohomail.com; s=zohoarc; b=PXI+EtaVKkrCM3eHck0NoNJxPpW8HOyJwxmGdLYX5Ljkr3vl252UvVimLAF2R4J+tMzUKaQ5KPhGX7PK4Jo3IK4/hFvGFf62+/PBBm3lverriGSSusyIl0MPRABLB6aR8xC93DX8pYkkWhQWLXQyR8h74xq7SL3Kh/un6W8iRHE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1777383400; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=ndINuL6QIvXx9NNGe9DLNHQgIRcEsSwATo/VEV4bvgc=; b=fePT1wiaaU6Zp+K9kIIL8bHIKZD4eb7hUpbMSTzFWtkwnpLl8fVk2rMrUpdWL6qN07kBYj5pO5RibGfj9QALyLkt0FZ6M42cYYJV/oMQiauQgYiJuPqaWYhsOP9e9jYyqVBM3V9OgnAW2motaCQZDhB+TL9r4G9WxLE2k2tsNsg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 177738340017437.03753846619645; Tue, 28 Apr 2026 06:36:40 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wHibT-0005Wm-Uj; Tue, 28 Apr 2026 09:35:55 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wHdrg-00088S-46; Tue, 28 Apr 2026 04:32:20 -0400 Received: from m16.mail.163.com ([117.135.210.3]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wHdrZ-0004Ay-9Z; Tue, 28 Apr 2026 04:32:19 -0400 Received: from PC-YLX4Y6J2.company.local (unknown []) by gzga-smtp-mtada-g1-1 (Coremail) with SMTP id _____wCHeop0cPBplDlxCA--.30779S2; Tue, 28 Apr 2026 16:31:49 +0800 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=nd INuL6QIvXx9NNGe9DLNHQgIRcEsSwATo/VEV4bvgc=; b=eOi4rsRL7Tddem8R/u pAx64XiyAalnpSC/G07nFxBA+l4WOS16/fS6BZK7oz78iMK7rP/GNJgIWKjVzGmt 6NKJ22IcHR8OAcSKeT0vCQCvvUdz9jeNAb+i11Am9Su0LwbHAYjoZBa7fLETuhh1 g8Vh7Sa9y3z82E28Xh2iNMZ1U= From: liugan1 To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , liugan1 Subject: [PATCH] hw/intc/arm_gicv3: Fix NS write to ICC_AP1Rn_EL1 when prebits < 7 Date: Tue, 28 Apr 2026 16:31:18 +0800 Message-ID: <20260428083119.1400110-1-gs_liugan@163.com> X-Mailer: git-send-email 2.50.1 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wCHeop0cPBplDlxCA--.30779S2 X-Coremail-Antispam: 1Uf129KBjvJXoWxJF1fGw1DWry7tw1ftFW5Jrb_yoWrAFykpF s3G34fur4kt3WSvwsxtF4UZFyF9FZ5XF45CrsrK34UCrn8AF18Xw4akFyYk34jkr4DJF1a qrn0vrWkuFZ8XFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jCQ6LUUUUU= X-Originating-IP: [220.248.55.69] X-CM-SenderInfo: xjvbzxhxjd0qqrwthudrp/xtbC5BbP-WnwcHZjxQAA35 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=117.135.210.3; envelope-from=gs_liugan@163.com; helo=m16.mail.163.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Tue, 28 Apr 2026 09:35:54 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @163.com) X-ZM-MESSAGEID: 1777383402776154100 Content-Type: text/plain; charset="utf-8" From: liugan1 The existing code uses a blanket `regno < 2` check to make ICC_AP1R0_EL1 and ICC_AP1R1_EL1 writes from Non-secure code WI (Write Ignore) when EL3 is present. This is intended to prevent NS code from claiming active interrupts in the Secure priority range, which could block Secure interrupt delivery. However, that check assumes prebits=3D7 (4 APR registers), where the NS priority range (128..255) maps entirely to AP1R2/AP1R3. Since commit 39f29e599355 ("hw/intc/arm_gicv3: Use correct number of priority bits for the CPU", first in 7.1), all QEMU AArch64 CPUs are initialised with gic_pribits=3D5 (one APR register), so NS priorities map to AP1R0 bits [16:31]. Blanket WI of the entire AP1R0 register prevents NS code from clearing its own NS active priority bits. Machines using hw_compat_7_0 (e.g. virt-7.0) still force pribits=3D8 via force-8-bit-prio and are therefore unaffected. A concrete consequence observed in virtualisation scenarios: when a guest VM acknowledges an SPI interrupt but does not perform EOI, is force-killed and restarted, the new guest's attempt to clear the residual active state by writing ICC_AP1R0_EL1=3D0 is silently ignored. The running priority (RPR) remains stuck at the old interrupt's priority, preventing all equal-or-lower priority interrupts (including timer interrupts) from being delivered, and hanging the guest. Fix this by computing the exact Secure/NS boundary within the APR bank based on prebits. For registers entirely in the Secure range, keep the WI behaviour. For the register that straddles the boundary, preserve only the Secure bits while allowing NS bits to be modified. For registers entirely in the NS range, allow full write access. The new logic produces identical behaviour to the old code when prebits=3D7, preserving existing behaviour for machines that use force-8-bit-prio. Fixes: 39f29e599355 ("hw/intc/arm_gicv3: Use correct number of priority bit= s for the CPU") Signed-off-by: liugan1 --- hw/intc/arm_gicv3_cpuif.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index fcb3922fa0..921d1fdfde 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -1869,9 +1869,40 @@ static void icc_ap_write(CPUARMState *env, const ARM= CPRegInfo *ri, * at a priority outside the Non-secure range (128..255), since this * would otherwise allow malicious NS code to block delivery of S inte= rrupts * by writing a bad value to these registers. + * + * The NS priority range (128..255) maps to APR bits starting at + * aprbit =3D 0x80 >> (8 - prebits). Depending on prebits, this bounda= ry + * may fall within AP1R0 or AP1R1, so we cannot simply WI the entire + * register. Instead we calculate which bits within each register + * correspond to the Secure range and preserve those, while allowing + * NS code to modify only the NS range bits. + * + * prebits=3D4: num_aprs=3D1, NS starts at AP1R0[8] + * prebits=3D5: num_aprs=3D1, NS starts at AP1R0[16] + * prebits=3D6: num_aprs=3D2, NS starts at AP1R1[0] + * prebits=3D7: num_aprs=3D4, NS starts at AP1R2[0] */ - if (grp =3D=3D GICV3_G1NS && regno < 2 && arm_feature(env, ARM_FEATURE= _EL3)) { - return; + if (grp =3D=3D GICV3_G1NS && arm_feature(env, ARM_FEATURE_EL3)) { + int ns_start_bit =3D 0x80 >> (8 - cs->prebits); + int ns_start_regno =3D ns_start_bit / 32; + int ns_start_regbit =3D ns_start_bit % 32; + + if (regno < ns_start_regno) { + /* This entire register is in the Secure range: WI */ + return; + } else if (regno =3D=3D ns_start_regno && ns_start_regbit > 0) { + /* + * This register is split: low bits are Secure, high bits are = NS. + * Preserve the Secure bits (below ns_start_regbit) from the + * current value, and take the NS bits (at and above + * ns_start_regbit) from the written value. + */ + uint32_t secure_mask =3D MAKE_64BIT_MASK(0, ns_start_regbit); + + value =3D (cs->icc_apr[grp][regno] & secure_mask) | + (value & ~secure_mask); + } + /* else: regno > ns_start_regno, entire register is NS: allow writ= e */ } =20 if (cs->nmi_support) { --=20 2.48.1