Reviewed-by: Glenn Miles <mil...@linux.ibm.com>

On Mon, 2025-05-12 at 13:10 +1000, Nicholas Piggin wrote:
> xive_tctx_pipr_present() as implemented with xive_tctx_pipr_update()
> causes VP-directed (group==0) interrupt to be presented in PIPR and NSR
> despite being a lower priority than the currently presented group
> interrupt.
> 
> This must not happen. The IPB bit should record the low priority VP
> interrupt, but PIPR and NSR must not present the lower priority
> interrupt.
> 
> Signed-off-by: Nicholas Piggin <npig...@gmail.com>
> ---
>  hw/intc/xive.c | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/intc/xive.c b/hw/intc/xive.c
> index bf4c0634ca..25f6c69c44 100644
> --- a/hw/intc/xive.c
> +++ b/hw/intc/xive.c
> @@ -228,7 +228,23 @@ void xive_tctx_pipr_update(XiveTCTX *tctx, uint8_t ring, 
> uint8_t priority,
>  void xive_tctx_pipr_present(XiveTCTX *tctx, uint8_t ring, uint8_t priority,
>                              uint8_t group_level)
>  {
> -    xive_tctx_pipr_update(tctx, ring, priority, group_level);
> +    /* HV_POOL ring uses HV_PHYS NSR, CPPR and PIPR registers */
> +    uint8_t alt_ring = (ring == TM_QW2_HV_POOL) ? TM_QW3_HV_PHYS : ring;
> +    uint8_t *aregs = &tctx->regs[alt_ring];
> +    uint8_t *regs = &tctx->regs[ring];
> +    uint8_t pipr = xive_priority_to_pipr(priority);
> +
> +    if (group_level == 0) {
> +        regs[TM_IPB] |= xive_priority_to_ipb(priority);
> +        if (pipr >= aregs[TM_PIPR]) {
> +            /* VP interrupts can come here with lower priority than PIPR */
> +            return;
> +        }
> +    }
> +    g_assert(pipr <= xive_ipb_to_pipr(regs[TM_IPB]));
> +    g_assert(pipr < aregs[TM_PIPR]);
> +    aregs[TM_PIPR] = pipr;
> +    xive_tctx_notify(tctx, ring, group_level);
>  }
>  
>  /*


Reply via email to