target/arm: GICv5 cpuif: Don't set HPPIV bit in GICv5PendingIrq::intid
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 <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-id: 20260512093856.3197700-3-peter.maydell@linaro.org
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user