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);
> }
>
> /*