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

Re: [PATCH v8 02/13] xen/arm: gic-v2: Implement GIC suspend/resume functions


  • To: Luca Fancellu <Luca.Fancellu@xxxxxxx>
  • From: Mykola Kvach <xakep.amatop@xxxxxxxxx>
  • Date: Thu, 7 May 2026 10:48:52 +0300
  • Arc-authentication-results: i=1; mx.google.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=FpH9ivn7J+a7CnqyryEVPZL0SHq/fQAbKBNReVXHWkM=; fh=uAzoxIkY79cy0zES8IqO07ArU7DBG3jlr2bg4XRVkR0=; b=fqUPtk7fNfk/3pn9ur5iswJsAyxFZ65cIUXORd83fL+EDgcRZxT6g4dW5YfxG2JQmD sJpAGInLi0fT5g+7clz+oOtxHoBoK/x0+piJclPScTldqeQhtB+r+TxuMilhCMAk+sYW gFaYFx/yrVRnDzGPnlUYp2O2mcbrLcPlT3SGaZMAxv4BMlo4aNPodwVWeNhMKHaSgecr Sfmqmom0P97118xAjoYtSQZ3GxPRUeiE/Peed2xXwFChLzIrhdh37X7EZ21if5mEzvFE winKeZHDkuQXk0F3CFH+iO/EbH3ldoYc70teK01hHH5GQp3v37bhXMYKsVbKX0niB/US g8fQ==; darn=lists.xenproject.org
  • Arc-seal: i=1; a=rsa-sha256; t=1778140145; cv=none; d=google.com; s=arc-20240605; b=KGkt4Rv1OZEfFY5XjGw+4yDnbNUSoMGB8rurbwV3N3NNh95ejA3C3i2fv6SpM3fl1O MELl+WLwQnq8Iu82zMAbwz3CvDubUt5vvdNvChIV7hWvjkefP4KgBuB/YiPBlOuFe5+r N2pnl3d+CGkVswU1OJg32298KE+/17aLmZ8lUTYDIn50/k5UAAVWdtAy2e8bwX4yi/kj /kPG9spB/UHBPBLFkYDewFX28Dd6K8XjIFfniRvoiGYqLAhAZCYJax7DrLF8RJSezca9 76Mf0u6X7VyCT5uGvsNzcmzSbCJ4fEzaRARrEALy5cZgTYjxWu+bbXFKDThP0ZGzptqK URxQ==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=20251104 header.d=gmail.com header.i="@gmail.com" header.h="Content-Transfer-Encoding:Cc:To:Subject:Message-ID:Date:From:In-Reply-To:References:MIME-Version"
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Mykola Kvach <mykola_kvach@xxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <Bertrand.Marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Thu, 07 May 2026 07:49:21 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Hi Luca,

Thank you for the feedback.

On Tue, Apr 21, 2026 at 4:26 PM Luca Fancellu <Luca.Fancellu@xxxxxxx> wrote:
>
> Hi Mykola,
>
> >
> > diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
> > index b23e72a3d0..dbff470962 100644
> > --- a/xen/arch/arm/gic-v2.c
> > +++ b/xen/arch/arm/gic-v2.c
> > @@ -1098,6 +1098,129 @@ static int gicv2_iomem_deny_access(struct domain *d)
> >     return iomem_deny_access(d, mfn, mfn + nr);
> > }
> >
> > +#ifdef CONFIG_SYSTEM_SUSPEND
> > +
> > +/* This struct represents block of 32 IRQs */
> > +struct irq_block {
> > +    uint32_t icfgr[2]; /* 2 registers of 16 IRQs each */
> > +    uint32_t ipriorityr[8];
> > +    uint32_t isenabler;
> > +    uint32_t isactiver;
> > +    uint32_t itargetsr[8];
> > +};
> > +
> > +/* GICv2 registers to be saved/restored on system suspend/resume */
> > +struct gicv2_context {
> > +    /* GICC context */
> > +    struct cpu_ctx {
> > +        uint32_t ctlr;
> > +        uint32_t pmr;
> > +        uint32_t bpr;
> > +    } cpu;
> > +
> > +    /* GICD context */
> > +    struct dist_ctx {
> > +        uint32_t ctlr;
> > +        /* Includes banked SGI/PPI state for the boot CPU. */
> > +        struct irq_block *irqs;
> > +    } dist;
> > +};
> > +
> > +static struct gicv2_context gic_ctx;
> > +
> > +static int gicv2_suspend(void)
> > +{
> > +    unsigned int i, blocks = DIV_ROUND_UP(gicv2_info.nr_lines, 32);
> > +
> > +    /* Save GICC_CTLR configuration. */
> > +    gic_ctx.cpu.ctlr = readl_gicc(GICC_CTLR);
> > +
> > +    /* Quiesce the GIC CPU interface before suspend. */
> > +    gicv2_cpu_disable();
> > +
> > +    /* Save GICD configuration */
> > +    gic_ctx.dist.ctlr = readl_gicd(GICD_CTLR);
> > +    writel_gicd(0, GICD_CTLR);
> > +
> > +    gic_ctx.cpu.pmr = readl_gicc(GICC_PMR);
> > +    gic_ctx.cpu.bpr = readl_gicc(GICC_BPR);
> > +
> > +    for ( i = 0; i < blocks; i++ )
> > +    {
> > +        struct irq_block *irqs = gic_ctx.dist.irqs + i;
> > +        size_t j, off = i * sizeof(irqs->isenabler);
> > +
> > +        irqs->isenabler = readl_gicd(GICD_ISENABLER + off);
> > +        irqs->isactiver = readl_gicd(GICD_ISACTIVER + off);
> > +
> > +        off = i * sizeof(irqs->ipriorityr);
> > +        for ( j = 0; j < ARRAY_SIZE(irqs->ipriorityr); j++ )
> > +        {
> > +            irqs->ipriorityr[j] = readl_gicd(GICD_IPRIORITYR + off + j * 
> > 4);
> > +            irqs->itargetsr[j] = readl_gicd(GICD_ITARGETSR + off + j * 4);
>
> regarding GICD_ITARGETSR ...
>
> > +        }
> > +
> > +        off = i * sizeof(irqs->icfgr);
> > +        for ( j = 0; j < ARRAY_SIZE(irqs->icfgr); j++ )
> > +            irqs->icfgr[j] = readl_gicd(GICD_ICFGR + off + j * 4);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static void gicv2_resume(void)
> > +{
> > +    unsigned int i, blocks = DIV_ROUND_UP(gicv2_info.nr_lines, 32);
> > +
> > +    gicv2_cpu_disable();
> > +    /* Disable distributor */
> > +    writel_gicd(0, GICD_CTLR);
> > +
> > +    for ( i = 0; i < blocks; i++ )
> > +    {
> > +        struct irq_block *irqs = gic_ctx.dist.irqs + i;
> > +        size_t j, off = i * sizeof(irqs->isenabler);
> > +
> > +        writel_gicd(GENMASK(31, 0), GICD_ICENABLER + off);
> > +        writel_gicd(irqs->isenabler, GICD_ISENABLER + off);
> > +
> > +        writel_gicd(GENMASK(31, 0), GICD_ICACTIVER + off);
> > +        writel_gicd(irqs->isactiver, GICD_ISACTIVER + off);
> > +
> > +        off = i * sizeof(irqs->ipriorityr);
> > +        for ( j = 0; j < ARRAY_SIZE(irqs->ipriorityr); j++ )
> > +        {
> > +            writel_gicd(irqs->ipriorityr[j], GICD_IPRIORITYR + off + j * 
> > 4);
> > +            writel_gicd(irqs->itargetsr[j], GICD_ITARGETSR + off + j * 4);
>
> … please let me know if I read correctly this loop, but here GICD_ITARGETSR0 
> … 7
> are restored when i=0, but the specificaitons says that this block is read 
> only on
> multiprocessor, so we should skip the restore part.
> Also saving it could be skipped because each field returns a value that 
> corresponds
> only to the processor reading the register.
>
> 4.3.12 User constraints [1]

You are right, thanks for pointing this out.
I will skip saving/restoring the read-only GICD_ITARGETSR0..7 block in v9.

>
> > +        }
> > +
> > +        off = i * sizeof(irqs->icfgr);
> > +        for ( j = 0; j < ARRAY_SIZE(irqs->icfgr); j++ )
> > +            writel_gicd(irqs->icfgr[j], GICD_ICFGR + off + j * 4);
> > +    }
> > +
> > +    /* Make sure all registers are restored and enable distributor */
> > +    writel_gicd(gic_ctx.dist.ctlr, GICD_CTLR);
> > +
> > +    /* Restore GIC CPU interface configuration */
> > +    writel_gicc(gic_ctx.cpu.pmr, GICC_PMR);
> > +    writel_gicc(gic_ctx.cpu.bpr, GICC_BPR);
> > +
> > +    /* Enable GIC CPU interface */
> > +    writel_gicc(gic_ctx.cpu.ctlr, GICC_CTLR);
> > +}
> > +
>
> I also see that we don’t save pending SGIs state (by 
> GICD_CPENDSGIRn/GICD_SPENDSGIRn) or Active Priorities registers
> state (GICC_APRn/GICC_NSAPRn [latter if security extension are there]) as 
> written in [1] “4.5 Preserving and restoring GIC state”,
> was it intentional?

Yes, this was intentional.

The GICv2 suspend callback is called at a quiescent point in the
SYSTEM_SUSPEND path: all domains are already shut down for suspend, guest
execution is quiesced, the scheduler is disabled, non-boot CPUs have been
offlined, and CPU0 enters gic_suspend() with local interrupts disabled.

For SGIs, I don't consider GICD_CPENDSGIRn/GICD_SPENDSGIRn part of the saved
host GIC context. Xen uses physical SGIs as IPIs, and IPI delivery is an
internal synchronization mechanism, not architectural state that should be
replayed after SYSTEM_SUSPEND. Guest SGI state is virtual GIC state and is not
represented by these physical GICD SGI pending registers.

For GICC_APRn/GICC_NSAPRn, those registers describe active priority state for
interrupts already acknowledged by the CPU interface. The final suspend path is
not expected to run with an active physical interrupt context. If those
registers were non-zero there, restoring only APR/NSAPR would not make the
corresponding interrupt handling context valid after resume, and could instead
leave the CPU interface with stale active priority state.

So I did not add save/restore for GICD_CPENDSGIRn/GICD_SPENDSGIRn or
GICC_APRn/GICC_NSAPRn in this patch. I can add a short comment in v9 to make
this scope explicit.

Please let me know if you think there is a suspend/resume path where this
state still needs to be preserved.

Best regards,
Mykola

>
> [1] https://developer.arm.com/documentation/ihi0048/bb/?lang=en
>
> Cheers,
> Luca
>
>



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.