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
next prev 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).