From 9ec3a7a53ce8ba8b09bfe567c2be66ce2ecb1df6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 12 May 2026 10:38:54 +0100 Subject: [PATCH] target/arm: GICv5 cpuif: Don't set HPPIV bit in GICv5PendingIrq::intid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In gic_hppi() we return the current highest priority pending interrupt in a GICv5PendingIrq struct. We try to set up the intid field of that struct to be the form that is used by the ICC_HPPIR register, which has a "valid" bit in bit 33. Unfortunately the GICv5PendingIrq defines the intid field as a uint32_t, so Coverity points out that the bit doesn't actually fit. Move the handling of the valid bit to the callsite, and make this function report "no pending interrupt" with GICv5PendingIrq::prio == PRIO_IDLE, consistently with how we use this struct in other places. CID: 1659594 Fixes: 9edad4ff3 ("target/arm: GICv5 cpuif: Implement ICC_HPPIR_EL1") Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Message-id: 20260512093856.3197700-3-peter.maydell@linaro.org --- include/hw/intc/arm_gicv5_types.h | 2 ++ target/arm/tcg/gicv5-cpuif.c | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/include/hw/intc/arm_gicv5_types.h b/include/hw/intc/arm_gicv5_types.h index eaed42f49f..de4f78a149 100644 --- a/include/hw/intc/arm_gicv5_types.h +++ b/include/hw/intc/arm_gicv5_types.h @@ -97,6 +97,8 @@ typedef enum GICv5TriggerMode { * * In this struct the intid includes the interrupt type in bits * [31:29] (i.e. it is in the form defined by R_TJPHS). + * + * "No pending interrupt" is represented by @prio == PRIO_IDLE. */ typedef struct GICv5PendingIrq { uint32_t intid; diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c index 98238ada19..dd2f696511 100644 --- a/target/arm/tcg/gicv5-cpuif.c +++ b/target/arm/tcg/gicv5-cpuif.c @@ -129,10 +129,9 @@ static GICv5PendingIrq gic_hppi(CPUARMState *env, GICv5Domain domain) { /* * Return the current highest priority pending interrupt for the - * specified domain, if it has sufficient priority to preempt. The - * intid field of the return value will be in the format of the - * ICC_HPPIR register (and will be zero if and only if there is no - * interrupt that can preempt). + * specified domain, if it has sufficient priority to preempt. + * If there is no interrupt that can preempt we signal this by + * returning a struct with prio == PRIO_IDLE. */ GICv5Common *gic = gicv5_get_gic(env); @@ -166,7 +165,6 @@ static GICv5PendingIrq gic_hppi(CPUARMState *env, GICv5Domain domain) best.prio >= gic_running_prio(env, domain)) { return (GICv5PendingIrq) { .intid = 0, .prio = PRIO_IDLE }; } - best.intid |= R_ICC_HPPIR_EL1_HPPIV_MASK; return best; } @@ -575,7 +573,12 @@ static uint64_t gic_icc_hppir_el1_read(CPUARMState *env, const ARMCPRegInfo *ri) { GICv5Domain domain = gicv5_logical_domain(env); GICv5PendingIrq hppi = gic_hppi(env, domain); - return hppi.intid; + + if (hppi.prio == PRIO_IDLE) { + /* No valid interrupt */ + return 0; + } + return hppi.intid | R_ICC_HPPIR_EL1_HPPIV_MASK; } static bool gic_hppi_is_nmi(CPUARMState *env, GICv5PendingIrq hppi, @@ -602,13 +605,12 @@ static uint64_t gicr_cdia_read(CPUARMState *env, const ARMCPRegInfo *ri) bool cdnmia = ri->opc2 == 1; - if (!hppi.intid) { + if (hppi.prio == PRIO_IDLE) { /* No interrupt available to acknowledge */ trace_gicv5_gicr_cdia_fail(domain, "no available interrupt to acknowledge"); return 0; } - assert(hppi.prio != PRIO_IDLE); if (gic_hppi_is_nmi(env, hppi, domain) != cdnmia) { /* GICR CDIA only acknowledges non-NMI; GICR CDNMIA only NMI */