xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@linaro.org>
To: Ian Campbell <Ian.Campbell@citrix.com>, vijay.kilari@gmail.com
Cc: Prasun.Kapoor@caviumnetworks.com,
	vijaya.kumar@caviumnetworks.com, xen-devel@lists.xen.org,
	stefano.stabellini@citrix.com, stefano.stabellini@eu.citrix.com
Subject: Re: [PATCH v3 13/16] xen/arm: Add support for GIC v3
Date: Tue, 27 May 2014 19:17:59 +0100	[thread overview]
Message-ID: <5384D6D7.7030109@linaro.org> (raw)
In-Reply-To: <1398272466.18537.222.camel@kazak.uk.xensource.com>

On 04/23/2014 06:01 PM, Ian Campbell wrote:
> On Tue, 2014-04-15 at 16:47 +0530, vijay.kilari@gmail.com wrote:
> 
>> +#include <xen/config.h>
>> +#include <xen/lib.h>
>> +#include <xen/init.h>
>> +#include <xen/cpu.h>
>> +#include <xen/mm.h>
>> +#include <xen/irq.h>
>> +#include <xen/sched.h>
>> +#include <xen/errno.h>
>> +#include <xen/serial.h>
>> +#include <xen/softirq.h>
>> +#include <xen/list.h>
>> +#include <xen/device_tree.h>
>> +#include <xen/delay.h>
>> +#include <asm/p2m.h>
>> +#include <asm/domain.h>
>> +#include <asm/platform.h>
> 
> Do you really need all of these? serial.h for example?
> 
>> +
>> +#include <asm/gic_v3_defs.h>
>> +#include <asm/gic.h>
>> +#include <asm/io.h>
>> +#include <asm/device.h>
>> +
>> +static struct gic_hw_operations gic_ops;
>> +
>> +struct rdist_region {
>> +    paddr_t rdist_base;
>> +    paddr_t rdist_base_size;
>> +    void __iomem *map_rdist_base;
> 
> "base", "size" and "map" would be adequate field names I think.
> 
>> +};
>> +
>> +/* Global state */
>> +static struct {
>> +    paddr_t dbase;            /* Address of distributor registers */
>> +    paddr_t dbase_size;
>> +    void __iomem *map_dbase;  /* Mapped address of distributor registers */
>> +    struct rdist_region *rdist_regions;
>> +    u32  rdist_stride;
>> +    unsigned int rdist_count; /* Number of rdist regions count */
>> +    unsigned int lines;       /* Number of interrupts (SPIs + PPIs + SGIs) */
>> +    struct dt_irq maintenance;
>> +}gic;
>> +
>> +/* per-cpu re-distributor base */
>> +static DEFINE_PER_CPU(void __iomem*, rbase);
> 
> Does this end up containing one of the gic.rdist_regions[i].map entries?
> Any reason to duplicate this in that map field as well? Can't each
> processor map it as it is initialised and store it here directly?
> 
> I suppose we have plenty of ioremap space on v8, so nr_cpus*2*64k isn't
> too bad and there's no need to go for per-pcpu pagetables with a
> dedicated virtual address region for the redistributors.
> 
>> +static u64 gich_read_lr(int lr)
>> +{
>> +    switch ( lr )
>> +    {
>> +    case 0: /* ICH_LRn is 64 bit */
>> +        return READ_SYSREG(ICH_LR0_EL2);
>> +        break;
> 
> All of these breaks are redundant. I think you could get away with
> 	case N: return READ_(..._LRn_EL2);
> for brevity even.
>> +
>> +/* Wait for completion of a distributor change */
>> +static void gicv3_do_wait_for_rwp(void __iomem *base)
>> +{
>> +    u32 val;
>> +    u32 count = 1000000;
>> +
>> +    do {
>> +        val = readl_relaxed(base + GICD_CTLR);
>> +        if ( !(val & GICD_CTLR_RWP) )
>> +           break;
>> +        cpu_relax();
>> +        udelay(1);
> 
> Ick. Is there no event when rwp changes, so we could do wfe here?
> 
> Could we at least use NOW() and MILLISECS() to construct a delay of a
> known length?
> 
>> +    } while ( count-- );
>> +
>> +    if ( !count )
>> +        dprintk(XENLOG_WARNING, "RWP timeout\n");
> 
> Shouldn't we panic here?
> 
> And if we are going to panic, we might as well wait forever? (Perhaps
> with a warning after some number of iterations.
> 
>> +static unsigned int gicv3_mask_cpu(const cpumask_t *cpumask)
> 
> this returns an arbitrary cpu from cpumask? Can we name it as such
> please.
> 
> The v2 equivalent returns a value suitable for GICD_ITARGETSR, which
> might contain multiple valid target CPUs. Does GICD_IROUTER not have the
> same property?
> 
>> +{
>> +    unsigned int cpu;
>> +    cpumask_t possible_mask;
>> +
>> +    cpumask_and(&possible_mask, cpumask, &cpu_possible_map);
>> +    cpu = cpumask_any(&possible_mask);
>> +    return cpu;
>> +}
>> +
>> +static void write_aprn_regs(union gic_state_data *d)
> 
> Given the usage I think this should be restore_aprn_regs.
> 
>> +{
>> +    ASSERT((nr_priorities > 4 && nr_priorities < 8));
>> +    /* Write APRn register based on number of priorities
>> +       plaform has implemented */
> 
> "platform"
> 
>> +    switch ( nr_priorities )
>> +    {
>> +    case 7:
>> +        WRITE_SYSREG32(d->v3.apr0[2], ICH_AP0R2_EL2);
>> +        WRITE_SYSREG32(d->v3.apr1[2], ICH_AP1R2_EL2);
>> +        /* Fall through */
>> +    case 6:
>> +        WRITE_SYSREG32(d->v3.apr0[1], ICH_AP0R1_EL2);
>> +        WRITE_SYSREG32(d->v3.apr1[1], ICH_AP1R1_EL2);
>> +        /* Fall through */
>> +    case 5:
>> +        WRITE_SYSREG32(d->v3.apr0[0], ICH_AP0R0_EL2);
>> +        WRITE_SYSREG32(d->v3.apr1[0], ICH_AP1R0_EL2);
>> +        break;
>> +    default:
> 
> BUG_ON?
> 
>> +        break;
>> +    }
>> +}
>> +
>> +static void read_aprn_regs(union gic_state_data *d)
> 
> The same three comments as write_* apply here too.
> 
>> +static void gicv3_save_state(struct vcpu *v)
>> +{
>> +    int i;
>> +
>> +    /* No need for spinlocks here because interrupts are disabled around
>> +     * this call and it only accesses struct vcpu fields that cannot be
>> +     * accessed simultaneously by another pCPU.
>> +     */
>> +    for ( i = 0; i < nr_lrs; i++)
>> +        v->arch.gic.v3.lr[i] = gich_read_lr(i);
>> +
>> +    read_aprn_regs(&v->arch.gic); 
>> +    v->arch.gic.v3.vmcr = READ_SYSREG32(ICH_VMCR_EL2);
>> +}
>> +
>> +static void gicv3_restore_state(struct vcpu *v)
>> +{
>> +    int i;
>> +
>> +    for ( i = 0; i < nr_lrs; i++)
>> +        gich_write_lr(i, v->arch.gic.v3.lr[i]);
> 
> I wonder if the compiler could do a better job of this using the same
> switch and fallthrough method you used for aprn regs?
> 
>> +
>> +    write_aprn_regs(&v->arch.gic);
>> +
>> +    WRITE_SYSREG32(v->arch.gic.v3.vmcr, ICH_VMCR_EL2);
>> +}
> 
>> +static void gicv3_enable_irq(struct irq_desc *irqd)
>> +{
>> +    int irq = irqd->irq;
>> +    uint32_t enabler;
>> +
>> +    /* Enable routing */
>> +    if ( irq < NR_GIC_LOCAL_IRQS )
>> +    {
>> +        enabler = readl_relaxed(GICD_RDIST_SGI_BASE + GICR_ISENABLER0);
>> +        enabler |= (1u << irq);
>> +        writel_relaxed(enabler, GICD_RDIST_SGI_BASE + GICR_ISENABLER0);
> 
> I don't think the enable registers need read-modufy-wirte, do they? You
> just write the bit you want to enable, like you do with the clear
> ICENABLER registers.
> 
>> +static u64 gic_mpidr_to_affinity(u64 mpidr)
>> +{
>> +    u64 aff;
>> +    /* Make sure we don't broadcast the interrupt */
>> +     aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 32 |
> 
> Indentation here is squiffy.
> 
>> +            MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
>> +            MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8  |
>> +            MPIDR_AFFINITY_LEVEL(mpidr, 0)) & ~GICD_IROUTER_SPI_MODE_ANY;
>> +    return aff;
>> +}
>> +
>> +/*
>> + * - needs to be called with gic.lock held
>> + * - needs to be called with a valid cpu_mask, ie each cpu in the mask has
>> + * already called gic_cpu_init
>> + */
>> +static void gicv3_set_irq_property(unsigned int irq, bool_t level,
>> +                                   const cpumask_t *cpu_mask,
>> +                                   unsigned int priority)
>> +{
>> +    uint32_t cfg, edgebit;
>> +    u64 affinity;
>> +    unsigned int cpu = gicv3_mask_cpu(cpu_mask);
>> +
>> +
>> +    /* Set edge / level */
>> +    if ( irq < NR_GIC_SGI )
>> +        /* SGI's are always edge-triggered not need to call GICD_ICFGR0 */
> 
> s/not/no/ I think.
> 
> But then given the comment you do anyway?
> 
>> +        cfg = readl_relaxed(GICD_RDIST_SGI_BASE + GICR_ICFGR0);
>> +    else if ( irq < NR_GIC_LOCAL_IRQS )
>> +        cfg = readl_relaxed(GICD_RDIST_SGI_BASE + GICR_ICFGR1);
>> +    else
>> +        cfg = readl_relaxed(GICD + GICD_ICFGR + (irq / 16) * 4);
>> +
>> +    edgebit = 2u << (2 * (irq % 16));
>> +    if ( level )
>> +        cfg &= ~edgebit;
>> +    else
>> +        cfg |= edgebit;
>> +
>> +    if ( irq < NR_GIC_SGI )
>> +       writel_relaxed(cfg, GICD_RDIST_SGI_BASE + GICR_ICFGR0);
>> +    else if ( irq < NR_GIC_LOCAL_IRQS )
>> +       writel_relaxed(cfg, GICD_RDIST_SGI_BASE + GICR_ICFGR1);
>> +    else
>> +       writel_relaxed(cfg, GICD + GICD_ICFGR + (irq / 16) * 4);
>> +
>> +    affinity = gic_mpidr_to_affinity(cpu_logical_map(cpu));
>> +    if ( irq >= NR_GIC_LOCAL_IRQS )
>> +        writeq_relaxed(affinity, (GICD + GICD_IROUTER + irq * 8));
>> +
>> +    /* Set priority */
>> +    if ( irq < NR_GIC_LOCAL_IRQS )
>> +    {
> 
> The {}s here aren't needed.
> 
>> +        writeb_relaxed(priority, GICD_RDIST_SGI_BASE + GICR_IPRIORITYR0 + irq);
>> +    }
>> +    else 
>> +    {
>> +        writeb_relaxed(priority, GICD + GICD_IPRIORITYR + irq);
>> +    }
>> +}
>> +
>> +static void gicv3_enable_redist(void)
>> +{
>> +    u32 val;
>> +    /* Wait for 1s */
>> +    u32 count = 1000000;
> 
> NOW() + MILLISECS(...) based again?
> 
>> +
>> +    /* Wake up this CPU redistributor */
>> +    val = readl_relaxed(GICD_RDIST_BASE + GICR_WAKER);
>> +    val &= ~GICR_WAKER_ProcessorSleep;
>> +    writel_relaxed(val, GICD_RDIST_BASE + GICR_WAKER);
>> +
>> +    do {
>> +         val = readl_relaxed(GICD_RDIST_BASE + GICR_WAKER);
>> +         if ( !(val & GICR_WAKER_ChildrenAsleep) )
>> +           break;
>> +         cpu_relax();
>> +         udelay(1);
>> +    } while ( count-- );
>> +
>> +    if ( !count )
>> +        gdprintk(XENLOG_WARNING, "Redist enable RWP timeout\n");
>> +}
>> +
>> +static int __init gicv3_populate_rdist(void)
>> +{
>> +    u64 mpidr = cpu_logical_map(smp_processor_id());
>> +    u64 typer;
>> +    uint32_t aff;
> 
> You have an interesting mix of u64 and uint32_t. Please stick to one or
> the other, preferable uintXX_t.
> 
>> +    int i;
>> +    uint32_t reg;
>> +
>> +    aff = (MPIDR_AFFINITY_LEVEL(mpidr, 3) << 24 |
>> +           MPIDR_AFFINITY_LEVEL(mpidr, 2) << 16 |
>> +           MPIDR_AFFINITY_LEVEL(mpidr, 1) << 8 |
>> +           MPIDR_AFFINITY_LEVEL(mpidr, 0));
> 
> Is this not gic_mpidr_to_affinity?

Actually it's not the same. The "level 3" is shift of 24 rather than 32.
This is to match TYPER register.

Linux code (where this function came from) has a comment above this
"Convert affinity to a 32bit value that can be matched to GICR_TYPER
bits [63:32]."

Regards,

-- 
Julien Grall

  parent reply	other threads:[~2014-05-27 18:17 UTC|newest]

Thread overview: 107+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-15 11:17 [PATCH v3 00/16] xen/arm: Add GICv3 support vijay.kilari
2014-04-15 11:17 ` [PATCH v3 01/16] xen/arm: move io.h as mmio.h to include folder vijay.kilari
2014-04-15 16:36   ` Julien Grall
2014-04-23 14:16   ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 02/16] xen/arm: make mmio handlers domain specific vijay.kilari
2014-04-15 17:07   ` Julien Grall
2014-04-23 14:27     ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 03/16] xen/arm: make sgi handling generic vijay.kilari
2014-04-15 17:51   ` Julien Grall
2014-04-15 17:57     ` Julien Grall
2014-04-23 14:31     ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 04/16] xen/arm: remove unused parameter in do_sgi call vijay.kilari
2014-04-15 17:52   ` Julien Grall
2014-04-23 14:32   ` Ian Campbell
2014-04-25  9:28     ` Vijay Kilari
2014-04-15 11:17 ` [PATCH v3 05/16] xen/arm: move gic definitions to seperate file vijay.kilari
2014-04-23 14:34   ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 06/16] xen/arm: move gic lock out of gic data structure vijay.kilari
2014-04-23 14:35   ` Ian Campbell
2014-05-12 13:49   ` Julien Grall
2014-04-15 11:17 ` [PATCH v3 07/16] xen/arm: segregate and split GIC low level functionality vijay.kilari
2014-04-15 18:35   ` Julien Grall
2014-04-23 14:55     ` Ian Campbell
2014-04-23 15:01       ` Julien Grall
2014-04-23 16:47         ` Julien Grall
2014-04-23 17:03           ` Ian Campbell
2014-04-23 17:09             ` Julien Grall
2014-04-24  8:58               ` Ian Campbell
2014-04-24  8:19           ` Ian Campbell
2014-04-28 11:48     ` Vijay Kilari
2014-04-28 12:06       ` Julien Grall
2014-04-28 13:10         ` Vijay Kilari
2014-04-28 13:12           ` Julien Grall
2014-04-15 21:00   ` Julien Grall
2014-04-23 14:52   ` Ian Campbell
2014-04-28 14:41     ` Vijay Kilari
2014-04-28 14:58       ` Ian Campbell
2014-04-28 15:10       ` Julien Grall
2014-04-15 11:17 ` [PATCH v3 08/16] arm/xen: move GIC context data structure to gic driver vijay.kilari
2014-04-15 18:41   ` Julien Grall
2014-04-23 14:57     ` Ian Campbell
2014-04-23 14:58   ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 09/16] xen/arm: use device api to detect GIC version vijay.kilari
2014-04-15 18:49   ` Julien Grall
2014-04-23 15:01   ` Ian Campbell
2014-04-29  7:07     ` Vijay Kilari
2014-04-29  8:55       ` Ian Campbell
2014-04-29 10:13         ` Julien Grall
2014-04-15 11:17 ` [PATCH v3 10/16] xen/arm: move vgic rank data to gic header file vijay.kilari
2014-04-15 19:10   ` Julien Grall
2014-04-17  6:48     ` Vijay Kilari
2014-05-07 15:03   ` Julien Grall
2014-04-15 11:17 ` [PATCH v3 11/16] xen/arm: move vgic defines to vgic " vijay.kilari
2014-04-16 17:01   ` Julien Grall
2014-04-23 15:07     ` Ian Campbell
2014-04-23 15:11       ` Julien Grall
2014-04-23 15:15         ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 12/16] xen/arm: split vgic driver into generic and vgic-v2 driver vijay.kilari
2014-04-15 20:05   ` Julien Grall
2014-04-23 15:12   ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 13/16] xen/arm: Add support for GIC v3 vijay.kilari
2014-04-15 20:43   ` Julien Grall
2014-04-17  7:09     ` Vijay Kilari
2014-04-17  8:58       ` Ian Campbell
2014-04-17  9:02       ` Julien Grall
2014-04-17  9:57   ` Julien Grall
2014-04-17 11:00     ` Vijay Kilari
2014-04-17 11:17       ` Julien Grall
2014-04-17 14:54         ` Vijay Kilari
2014-04-17 15:12           ` Julien Grall
2014-04-23 17:01   ` Ian Campbell
2014-04-23 17:24     ` Julien Grall
2014-04-29 12:35       ` Vijay Kilari
2014-05-05 12:08     ` Vijay Kilari
2014-05-06  8:55       ` Ian Campbell
2014-05-06 14:11         ` Vijay Kilari
2014-05-06 14:18           ` Julien Grall
2014-05-06 15:47             ` Julien Grall
2014-05-22  5:58               ` Vijay Kilari
2014-05-22  9:26                 ` Julien Grall
2014-05-22 12:36                   ` Stefano Stabellini
2014-05-07 16:30           ` Ian Campbell
2014-05-27 18:17     ` Julien Grall [this message]
2014-04-15 11:17 ` [PATCH v3 14/16] xen/arm: Add virtual GICv3 support vijay.kilari
2014-04-17  9:27   ` Julien Grall
2014-04-24 10:37     ` Ian Campbell
2014-04-24 11:39       ` Julien Grall
2014-04-24 10:30   ` Ian Campbell
2014-05-02  9:43     ` Vijay Kilari
2014-05-02  9:56       ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 15/16] xen/arm: Update Dom0 GIC dt node with GICv3 information vijay.kilari
2014-04-18 19:57   ` Julien Grall
2014-04-24 10:46   ` Ian Campbell
2014-04-15 11:17 ` [PATCH v3 16/16] xen/arm: add SGI handling for GICv3 vijay.kilari
2014-04-18 20:20   ` Julien Grall
2014-05-02 12:57     ` Vijay Kilari
2014-05-02 14:26       ` Julien Grall
2014-05-02 15:18         ` Ian Campbell
2014-05-02 15:24           ` Julien Grall
2014-05-05  6:53             ` Vijay Kilari
2014-05-05 18:40               ` Julien Grall
2014-05-06  8:58                 ` Ian Campbell
2014-05-06  9:42                   ` Julien Grall
2014-05-06 10:10                     ` Ian Campbell
2014-05-06 16:06                       ` Julien Grall
2014-04-24 10:57   ` Ian Campbell
2014-04-24 11:43     ` Julien Grall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5384D6D7.7030109@linaro.org \
    --to=julien.grall@linaro.org \
    --cc=Ian.Campbell@citrix.com \
    --cc=Prasun.Kapoor@caviumnetworks.com \
    --cc=stefano.stabellini@citrix.com \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=vijay.kilari@gmail.com \
    --cc=vijaya.kumar@caviumnetworks.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).