From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [PULL 12/28] hw/intc/arm_gicv3: Fix NS write to ICC_AP1Rn_EL1 when prebits < 7
Date: Fri, 1 May 2026 11:14:49 +0100 [thread overview]
Message-ID: <20260501101505.3485916-13-peter.maydell@linaro.org> (raw)
In-Reply-To: <20260501101505.3485916-1-peter.maydell@linaro.org>
From: liugan1 <liugan1@lixiang.com>
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=7 (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=5 (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=8 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=0 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=7, preserving existing behaviour for machines that use
force-8-bit-prio.
Fixes: 39f29e599355 ("hw/intc/arm_gicv3: Use correct number of priority bits for the CPU")
Cc: qemu-stable@nongnu.org
Signed-off-by: liugan1 <liugan1@lixiang.com>
Message-id: 20260428083119.1400110-1-gs_liugan@163.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
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 ARMCPRegInfo *ri,
* at a priority outside the Non-secure range (128..255), since this
* would otherwise allow malicious NS code to block delivery of S interrupts
* by writing a bad value to these registers.
+ *
+ * The NS priority range (128..255) maps to APR bits starting at
+ * aprbit = 0x80 >> (8 - prebits). Depending on prebits, this boundary
+ * 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=4: num_aprs=1, NS starts at AP1R0[8]
+ * prebits=5: num_aprs=1, NS starts at AP1R0[16]
+ * prebits=6: num_aprs=2, NS starts at AP1R1[0]
+ * prebits=7: num_aprs=4, NS starts at AP1R2[0]
*/
- if (grp == GICV3_G1NS && regno < 2 && arm_feature(env, ARM_FEATURE_EL3)) {
- return;
+ if (grp == GICV3_G1NS && arm_feature(env, ARM_FEATURE_EL3)) {
+ int ns_start_bit = 0x80 >> (8 - cs->prebits);
+ int ns_start_regno = ns_start_bit / 32;
+ int ns_start_regbit = ns_start_bit % 32;
+
+ if (regno < ns_start_regno) {
+ /* This entire register is in the Secure range: WI */
+ return;
+ } else if (regno == 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 = MAKE_64BIT_MASK(0, ns_start_regbit);
+
+ value = (cs->icc_apr[grp][regno] & secure_mask) |
+ (value & ~secure_mask);
+ }
+ /* else: regno > ns_start_regno, entire register is NS: allow write */
}
if (cs->nmi_support) {
--
2.43.0
next prev parent reply other threads:[~2026-05-01 10:17 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 10:14 [PULL 00/28] target-arm queue Peter Maydell
2026-05-01 10:14 ` [PULL 01/28] hw/arm/fsl-imx8mp: Do not create redundant unimplemented devices Peter Maydell
2026-05-01 10:14 ` [PULL 02/28] hw/arm/fsl-imx8mp: Fix parent of ocram memory region Peter Maydell
2026-05-01 10:14 ` [PULL 03/28] Revert "sysbus: add irq_routing_notifier" Peter Maydell
2026-05-01 10:14 ` [PULL 04/28] linux-user/arm: Restrict regpairs_aligned Peter Maydell
2026-05-01 10:14 ` [PULL 05/28] qemu-options: Improve description for -smb option Peter Maydell
2026-05-01 10:14 ` [PULL 06/28] target/arm/cpu-features.c: New fields in AA64MMFR4 Peter Maydell
2026-05-01 10:14 ` [PULL 07/28] target/arm/cpu.h: New GPCCR fields Peter Maydell
2026-05-01 10:14 ` [PULL 08/28] target/arm/ptw.c: Add GDI spaces to the granule protection case Peter Maydell
2026-05-01 10:14 ` [PULL 09/28] tests/tcg/aarch64/system/rme_gdi.c: Very basic test of GDI Peter Maydell
2026-05-01 10:14 ` [PULL 10/28] docs/devel/decodetree: Fix formatting in "field examples" table Peter Maydell
2026-05-01 10:14 ` [PULL 11/28] hw/net/allwinner-sun8i-emac: Flush queued packets when rx is enabled Peter Maydell
2026-05-01 10:14 ` Peter Maydell [this message]
2026-05-01 10:14 ` [PULL 13/28] target/arm/kvm: Cache host CPU probe failure Peter Maydell
2026-05-01 10:14 ` [PULL 14/28] hw/intc: Add hvf vGIC interrupt controller support Peter Maydell
2026-05-01 10:14 ` [PULL 15/28] hw/intc: arm_gicv3_hvf: save/restore Apple GIC state Peter Maydell
2026-05-07 8:08 ` Philippe Mathieu-Daudé
2026-06-13 11:45 ` Philippe Mathieu-Daudé
2026-06-13 11:49 ` Mohamed Mediouni
2026-05-01 10:14 ` [PULL 16/28] accel, hw/arm, include/system/hvf: infrastructure changes for HVF vGIC Peter Maydell
2026-05-01 10:14 ` [PULL 17/28] target/arm: hvf: instantiate GIC early Peter Maydell
2026-05-01 10:14 ` [PULL 18/28] hw/arm, target/arm: nested virtualisation on HVF Peter Maydell
2026-05-01 10:14 ` [PULL 19/28] hvf: only call hvf_sync_vtimer() when running without the platform vGIC Peter Maydell
2026-05-01 10:14 ` [PULL 20/28] hvf: gate ARM_FEATURE_PMU register emulation when using the Apple vGIC Peter Maydell
2026-05-01 10:14 ` [PULL 21/28] hvf: arm: allow exposing minimal PMU for kernel-irqchip=on Peter Maydell
2026-05-01 10:14 ` [PULL 22/28] target/arm: hvf: add asserts for code paths not leveraged when using the vGIC Peter Maydell
2026-05-01 10:15 ` [PULL 23/28] hvf: sync registers used at EL2 Peter Maydell
2026-05-01 10:59 ` Stefan Hajnoczi
2026-05-01 23:20 ` Mohamed Mediouni
2026-05-01 10:15 ` [PULL 24/28] target/arm: hvf: pass through CNTHCTL_EL2 and MDCCINT_EL1 Peter Maydell
2026-05-01 10:15 ` [PULL 25/28] hvf: arm: disable SME when nested virt is active Peter Maydell
2026-05-01 10:15 ` [PULL 26/28] hvf: arm: physical timer emulation Peter Maydell
2026-05-01 10:15 ` [PULL 27/28] hvf: enable nested virtualisation support Peter Maydell
2026-05-01 10:15 ` [PULL 28/28] hvf: arm: enable vGIC by default for virt-11.1 and later 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=20260501101505.3485916-13-peter.maydell@linaro.org \
--to=peter.maydell@linaro.org \
--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.