qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 22/50] ppc/xive2: Support redistribution of group interrupts


From: Nicholas Piggin
Subject: Re: [PATCH 22/50] ppc/xive2: Support redistribution of group interrupts
Date: Fri, 16 May 2025 10:19:01 +1000

On Mon May 12, 2025 at 1:10 PM AEST, Nicholas Piggin wrote:
> From: Glenn Miles <milesg@linux.ibm.com>
>
> When an XIVE context is pulled while it has an active, unacknowledged
> group interrupt, XIVE will check to see if a context on another thread
> can handle the interrupt and, if so, notify that context.  If there
> are no contexts that can handle the interrupt, then the interrupt is
> added to a backlog and XIVE will attempt to escalate the interrupt,
> if configured to do so, allowing the higher privileged handler to
> activate a context that can handle the original interrupt.

Reviewed-by: Nicholas Piggin <npiggin@gmail.com>

>
> Signed-off-by: Glenn Miles <milesg@linux.ibm.com>
> ---
>  hw/intc/xive2.c             | 84 +++++++++++++++++++++++++++++++++++--
>  include/hw/ppc/xive2_regs.h |  3 ++
>  2 files changed, 83 insertions(+), 4 deletions(-)
>
> diff --git a/hw/intc/xive2.c b/hw/intc/xive2.c
> index 0993e792cc..34fc561c9c 100644
> --- a/hw/intc/xive2.c
> +++ b/hw/intc/xive2.c
> @@ -19,6 +19,10 @@
>  #include "hw/ppc/xive2_regs.h"
>  #include "trace.h"
>  
> +static void xive2_router_end_notify(Xive2Router *xrtr, uint8_t end_blk,
> +                                    uint32_t end_idx, uint32_t end_data,
> +                                    bool redistribute);
> +
>  uint32_t xive2_router_get_config(Xive2Router *xrtr)
>  {
>      Xive2RouterClass *xrc = XIVE2_ROUTER_GET_CLASS(xrtr);
> @@ -597,6 +601,68 @@ static uint32_t xive2_tctx_hw_cam_line(XivePresenter 
> *xptr, XiveTCTX *tctx)
>      return xive2_nvp_cam_line(blk, 1 << tid_shift | (pir & tid_mask));
>  }
>  
> +static void xive2_redistribute(Xive2Router *xrtr, XiveTCTX *tctx,
> +                               uint8_t nvp_blk, uint32_t nvp_idx, uint8_t 
> ring)
> +{
> +    uint8_t nsr = tctx->regs[ring + TM_NSR];
> +    uint8_t crowd = NVx_CROWD_LVL(nsr);
> +    uint8_t group = NVx_GROUP_LVL(nsr);
> +    uint8_t nvgc_blk;
> +    uint8_t nvgc_idx;
> +    uint8_t end_blk;
> +    uint32_t end_idx;
> +    uint8_t pipr = tctx->regs[ring + TM_PIPR];
> +    Xive2Nvgc nvgc;
> +    uint8_t prio_limit;
> +    uint32_t cfg;
> +
> +    /* convert crowd/group to blk/idx */
> +    if (group > 0) {
> +        nvgc_idx = (nvp_idx & (0xffffffff << group)) |
> +                   ((1 << (group - 1)) - 1);
> +    } else {
> +        nvgc_idx = nvp_idx;
> +    }
> +
> +    if (crowd > 0) {
> +        crowd = (crowd == 3) ? 4 : crowd;
> +        nvgc_blk = (nvp_blk & (0xffffffff << crowd)) |
> +                   ((1 << (crowd - 1)) - 1);
> +    } else {
> +        nvgc_blk = nvp_blk;
> +    }
> +
> +    /* Use blk/idx to retrieve the NVGC */
> +    if (xive2_router_get_nvgc(xrtr, crowd, nvgc_blk, nvgc_idx, &nvgc)) {
> +        qemu_log_mask(LOG_GUEST_ERROR, "XIVE: no %s %x/%x\n",
> +                      crowd ? "NVC" : "NVG", nvgc_blk, nvgc_idx);
> +        return;
> +    }
> +
> +    /* retrieve the END blk/idx from the NVGC */
> +    end_blk = xive_get_field32(NVGC2_W1_END_BLK, nvgc.w1);
> +    end_idx = xive_get_field32(NVGC2_W1_END_IDX, nvgc.w1);
> +
> +    /* determine number of priorities being used */
> +    cfg = xive2_router_get_config(xrtr);
> +    if (cfg & XIVE2_EN_VP_GRP_PRIORITY) {
> +        prio_limit = 1 << GETFIELD(NVGC2_W1_PSIZE, nvgc.w1);
> +    } else {
> +        prio_limit = 1 << GETFIELD(XIVE2_VP_INT_PRIO, cfg);
> +    }
> +
> +    /* add priority offset to end index */
> +    end_idx += pipr % prio_limit;
> +
> +    /* trigger the group END */
> +    xive2_router_end_notify(xrtr, end_blk, end_idx, 0, true);
> +
> +    /* clear interrupt indication for the context */
> +    tctx->regs[ring + TM_NSR] = 0;
> +    tctx->regs[ring + TM_PIPR] = tctx->regs[ring + TM_CPPR];
> +    xive_tctx_reset_signal(tctx, ring);
> +}
> +
>  static uint64_t xive2_tm_pull_ctx(XivePresenter *xptr, XiveTCTX *tctx,
>                                    hwaddr offset, unsigned size, uint8_t ring)
>  {
> @@ -608,6 +674,7 @@ static uint64_t xive2_tm_pull_ctx(XivePresenter *xptr, 
> XiveTCTX *tctx,
>      uint8_t cur_ring;
>      bool valid;
>      bool do_save;
> +    uint8_t nsr;
>  
>      xive2_cam_decode(cam, &nvp_blk, &nvp_idx, &valid, &do_save);
>  
> @@ -624,6 +691,12 @@ static uint64_t xive2_tm_pull_ctx(XivePresenter *xptr, 
> XiveTCTX *tctx,
>          memcpy(&tctx->regs[cur_ring + TM_WORD2], &ringw2_new, 4);
>      }
>  
> +    /* Active group/crowd interrupts need to be redistributed */
> +    nsr = tctx->regs[ring + TM_NSR];
> +    if (xive_nsr_indicates_group_exception(ring, nsr)) {
> +        xive2_redistribute(xrtr, tctx, nvp_blk, nvp_idx, ring);
> +    }
> +
>      if (xive2_router_get_config(xrtr) & XIVE2_VP_SAVE_RESTORE && do_save) {
>          xive2_tctx_save_ctx(xrtr, tctx, nvp_blk, nvp_idx, ring);
>      }
> @@ -1352,7 +1425,8 @@ static bool xive2_router_end_es_notify(Xive2Router 
> *xrtr, uint8_t end_blk,
>   * message has the same parameters than in the function below.
>   */
>  static void xive2_router_end_notify(Xive2Router *xrtr, uint8_t end_blk,
> -                                    uint32_t end_idx, uint32_t end_data)
> +                                    uint32_t end_idx, uint32_t end_data,
> +                                    bool redistribute)
>  {
>      Xive2End end;
>      uint8_t priority;
> @@ -1380,7 +1454,7 @@ static void xive2_router_end_notify(Xive2Router *xrtr, 
> uint8_t end_blk,
>          return;
>      }
>  
> -    if (xive2_end_is_enqueue(&end)) {
> +    if (!redistribute && xive2_end_is_enqueue(&end)) {
>          xive2_end_enqueue(&end, end_data);
>          /* Enqueuing event data modifies the EQ toggle and index */
>          xive2_router_write_end(xrtr, end_blk, end_idx, &end, 1);
> @@ -1560,7 +1634,8 @@ do_escalation:
>          xive2_router_end_notify(xrtr,
>                                 xive_get_field32(END2_W4_END_BLOCK,     
> end.w4),
>                                 xive_get_field32(END2_W4_ESC_END_INDEX, 
> end.w4),
> -                               xive_get_field32(END2_W5_ESC_END_DATA,  
> end.w5));
> +                               xive_get_field32(END2_W5_ESC_END_DATA,  
> end.w5),
> +                               false);
>      } /* end END adaptive escalation */
>  
>      else {
> @@ -1641,7 +1716,8 @@ void xive2_notify(Xive2Router *xrtr , uint32_t lisn, 
> bool pq_checked)
>      xive2_router_end_notify(xrtr,
>                              xive_get_field64(EAS2_END_BLOCK, eas.w),
>                              xive_get_field64(EAS2_END_INDEX, eas.w),
> -                            xive_get_field64(EAS2_END_DATA,  eas.w));
> +                            xive_get_field64(EAS2_END_DATA,  eas.w),
> +                            false);
>      return;
>  }
>  
> diff --git a/include/hw/ppc/xive2_regs.h b/include/hw/ppc/xive2_regs.h
> index 2c535ec0d0..e222038143 100644
> --- a/include/hw/ppc/xive2_regs.h
> +++ b/include/hw/ppc/xive2_regs.h
> @@ -224,6 +224,9 @@ typedef struct Xive2Nvgc {
>  #define NVGC2_W0_VALID             PPC_BIT32(0)
>  #define NVGC2_W0_PGONEXT           PPC_BITMASK32(26, 31)
>          uint32_t        w1;
> +#define NVGC2_W1_PSIZE             PPC_BITMASK32(0, 1)
> +#define NVGC2_W1_END_BLK           PPC_BITMASK32(4, 7)
> +#define NVGC2_W1_END_IDX           PPC_BITMASK32(8, 31)
>          uint32_t        w2;
>          uint32_t        w3;
>          uint32_t        w4;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]