On Mon, Nov 25, 2013 at 10:00 AM, Anup Patel <anup@xxxxxxxxxxxxxx> wrote: > On Mon, Nov 25, 2013 at 9:13 PM, Rob Herring <robherring2@xxxxxxxxx> wrote: >> On Sat, Nov 23, 2013 at 2:41 AM, Anup Patel <anup@xxxxxxxxxxxxxx> wrote: >>> On Wed, Nov 20, 2013 at 4:28 PM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote: >>>> [dropping <patches@xxxxxxx> from the CC list, as someone seems to have >>>> tripped on the config file, and I'm tired of getting bounces] >>>> >>>> Feng, >>>> >>>> On 19/11/13 21:42, Feng Kan wrote: >>>>> The GIC-400 implementation allows for FIQ and IRQ bypass. In the >>>>> X-Gene implementation, the FIQ bypass must be enabled at all time. >>>>> Otherwise, some PPI will appear as FIQ and cause kernel problem. >>>> >>>> How comes? Are only PPIs affected? When you say "some PPIs", can you be >>>> more specific? >>>> >>>>> Signed-off-by: Feng Kan <fkan@xxxxxxx> >>>>> --- >>>>> drivers/irqchip/irq-gic.c | 15 +++++++++++---- >>>>> include/linux/irqchip/arm-gic.h | 4 ++-- >>>>> 2 files changed, 13 insertions(+), 6 deletions(-) >>>>> >>>>> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c >>>>> index d0e9480..aa7342e 100644 >>>>> --- a/drivers/irqchip/irq-gic.c >>>>> +++ b/drivers/irqchip/irq-gic.c >>>>> @@ -65,6 +65,7 @@ struct gic_chip_data { >>>>> #endif >>>>> struct irq_domain *domain; >>>>> unsigned int gic_irqs; >>>>> + unsigned int bypass_flag; >>>>> #ifdef CONFIG_GIC_NON_BANKED >>>>> void __iomem *(*get_base)(union gic_base *); >>>>> #endif >>>>> @@ -450,7 +451,7 @@ static void gic_cpu_init(struct gic_chip_data *gic) >>>>> writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); >>>>> >>>>> writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); >>>>> - writel_relaxed(1, base + GIC_CPU_CTRL); >>>>> + writel_relaxed(gic->bypass_flag | 1, base + GIC_CPU_CTRL); >>>>> } >>>>> >>>>> void gic_cpu_if_down(void) >>>>> @@ -591,7 +592,7 @@ static void gic_cpu_restore(unsigned int gic_nr) >>>>> writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); >>>>> >>>>> writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); >>>>> - writel_relaxed(1, cpu_base + GIC_CPU_CTRL); >>>>> + writel_relaxed(gic_data[gic_nr].bypass_flag | 1, cpu_base + GIC_CPU_CTRL); >>>>> } >>>>> >>>>> static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) >>>>> @@ -733,7 +734,8 @@ const struct irq_domain_ops gic_irq_domain_ops = { >>>>> >>>>> void __init gic_init_bases(unsigned int gic_nr, int irq_start, >>>>> void __iomem *dist_base, void __iomem *cpu_base, >>>>> - u32 percpu_offset, struct device_node *node) >>>>> + u32 percpu_offset, u32 bypass_val, >>>>> + struct device_node *node) >>>>> { >>>>> irq_hw_number_t hwirq_base; >>>>> struct gic_chip_data *gic; >>>>> @@ -821,6 +823,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, >>>>> >>>>> set_handle_irq(gic_handle_irq); >>>>> >>>>> + gic->bypass_flag = (bypass_val & 0xf) << 4; >>>> >>>> Beware, the top 2 bits are reserved on GICv1, and shouldn't be messed with. >>>> >>>>> gic_chip.flags |= gic_arch_extn.flags; >>>>> gic_dist_init(gic); >>>>> gic_cpu_init(gic); >>>>> @@ -835,6 +838,7 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) >>>>> void __iomem *cpu_base; >>>>> void __iomem *dist_base; >>>>> u32 percpu_offset; >>>>> + u32 bypass_val; >>>>> int irq; >>>>> >>>>> if (WARN_ON(!node)) >>>>> @@ -849,7 +853,10 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent) >>>>> if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) >>>>> percpu_offset = 0; >>>>> >>>>> - gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node); >>>>> + if (of_property_read_u32(node, "bypass-flags", &bypass_val)) >>>>> + bypass_val = 0; >>>> >>>> [adding Mark on Cc, so he can comment on the DT parts] >>>> >>>> Where's the DT documentation update? Also, as this is an >>>> implementation-specific quirk, you should consider using a separate >>>> compatible string and move the handling of this issue into some X-Gene >>>> specific code. >>> >>> Adding separate compatible string for X-Gene specific GIC will break >>> VGIC code for X-Gene because VGIC code looks for DT node compatible >>> to "arm,cortex-a15-gic". We don't want to break currently working VGIC >>> code for X-Gene. >>> >>> The Legacy-IRQ bypass disable and Legacy-FIQ bypass disable is a >>> feature of GIC-400 and its not X-Gene specific. The only difference in X-Gene >>> is that we use PPI31 (Legacy-IRQ) for timer and PPI28 (Legacy-FIQ) for perf >>> event. The issue is that IRQBypDisGrp0, FIQBypDisGrp0, IRQBypDisGrp1 >>> and FIQBypDisGrp1 bits are 0 by default and for X-Gene we need to set >>> these bits to 1 so that GIC-400 does not bypass PPI31 (Legacy-IRQ) and >>> PPI28 (Legacy-FIQ). >>> >>> We should have more cleaner and optional device tree binding for GIC >>> which can help us set IRQBypDisGrp0, FIQBypDisGrp0, IRQBypDisGrp1 >>> and FIQBypDisGrp1 bits for X-Gene. >> >> IIRC, all these bits are secure mode only (or only a subset are >> banked). Whether an SoC supports secure mode or not, the current >> policy for the kernel is to do any secure mode setup in firmware or >> bootloader. > > Group0 are secure interrupts and Group1 are non-secure interrupts. Right, but the non-secure view of the GIC has no concept of groups. They are only visible in secure mode. > Does this mean we should only touch IRQBypDisGrp1 and FIQBypDisGrp1 > bits from kernel ?? No, the kernel should only touch bits defined (by the GIC arch spec) to be available in non-secure mode. Specifically this is bit 0 only. I guess you will have to change accesses to cpu ctrl reg to a read-mod-write to preserve any bits you need set. Rob _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm