[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <53E1EACA.6070502@huawei.com>
Date: Wed, 6 Aug 2014 16:43:54 +0800
From: Liu hua <sdu.liu@...wei.com>
To: Marc Zyngier <marc.zyngier@....com>
CC: Will Deacon <Will.Deacon@....com>,
"nicolas.pitre@...aro.org" <nicolas.pitre@...aro.org>,
"linux@....linux.org.uk" <linux@....linux.org.uk>,
"linux-arm-kernel@...ts.infradead.org"
<linux-arm-kernel@...ts.infradead.org>,
"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
"peifeiyue@...wei.com" <peifeiyue@...wei.com>,
"liusdu@....com" <liusdu@....com>,
"wangnan0@...wei.com" <wangnan0@...wei.com>,
"ebiederm@...ssion.com" <ebiederm@...ssion.com>
Subject: Re: [PATCH V2 1/1] GIC: introduce method to deactive interupts
δΊ 2014/8/4 17:43, Marc Zyngier ει:
> Hi Liu,
>
> On 04/08/14 05:17, Liu Hua wrote:
>> When using kdump on ARM platform, if kernel panics in interrupt handler
>> (maybe PPI), the capture kernel can not recive certain interrupt, and
>> fails to boot.
>>
>> On this situation, We have read register GICC_IAR. But we have no chance
>> to write relative bit to register GICC_EOIR (kernel paniced before). So
>> the state of this type interrupt remains active. And that makes gic not
>> deliver this type interrupt to cpu interface.
>>
>> So we should not assume that all interrut states of GIC are inactive when
>> kernel inittailize the GIC. This patch will identify these type interrupts
>> and deactive them
>>
>> Signed-off-by: Liu Hua <sdu.liu@...wei.com>
>> ---
>> drivers/irqchip/irq-gic.c | 26 ++++++++++++++++++++++++++
>> 1 file changed, 26 insertions(+)
>>
>> diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
>> index b2648fc..7708df1 100644
>> --- a/drivers/irqchip/irq-gic.c
>> +++ b/drivers/irqchip/irq-gic.c
>> @@ -351,12 +351,37 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
>> return mask;
>> }
>>
>> +void gic_eois(u32 active, int irq_off, void __iomem *cpu_base)
>> +{
>> + int bit = -1;
>> +
>> + for_each_set_bit(bit, (unsigned long *)&active, 32)
>> + writel_relaxed(bit + irq_off, cpu_base + GIC_CPU_EOI);
>> +}
>> +
>> +void gic_dist_clear_active(void __iomem *dist_base,
>> + void __iomem *cpu_base, int gic_irqs)
>> +{
>> + int irq, offset;
>> + u32 active;
>> +
>> + for (irq = 0; irq < gic_irqs; irq += 32) {
>> + offset = GIC_DIST_ACTIVE_SET + irq * 4 / 32;
>> + active = readl_relaxed(dist_base + offset);
>> + if (!active)
>> + continue;
>> + gic_eois(active, irq, cpu_base);
>> + }
>> +}
>> +
>> +
>> static void __init gic_dist_init(struct gic_chip_data *gic)
>> {
>> unsigned int i;
>> u32 cpumask;
>> unsigned int gic_irqs = gic->gic_irqs;
>> void __iomem *base = gic_data_dist_base(gic);
>> + void __iomem *cpu_base = gic_data_cpu_base(gic);
>>
>> writel_relaxed(0, base + GIC_DIST_CTRL);
>>
>> @@ -371,6 +396,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
>>
>> gic_dist_config(base, gic_irqs, NULL);
>>
>> + gic_dist_clear_active(base, cpu_base, gic_irqs);
>> writel_relaxed(1, base + GIC_DIST_CTRL);
>> }
>
> So while this is solving a real issue, I don't think you can just fix it
> for the UP case. You'll have to fix the same thing for secondary CPUs
> (shouldn't be too hard to split things between local and global interrupts).
Hi Marc,
Thanks very much for you reply!
when I tried to implement your ideas. I found that: when kdump is deployed
and without my patch,
(1) panic in PPI, the capture kernel can not boot up.
(2) panic in SPI, the capture kernel boot up regularly.
I was confused and there may be something I did not catch. I glanced the kdump
code and found that function machine_kexec_mask_interrupts. It will clear the
GIC active state only if the IRQD_IRQ_INPROGRESS bit in d->state_use_accessors
is set.
And the PPI handler does not set this flag. So there are two ways to solve this
problem.
(1) consider this problem common, as you and I thought before. we should fix secondary CPUs issues;
(2)just set flag IRQD_IRQ_INPROGRESS in PPI. we need patch like this:
-------------(2) patch start-----------
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index a2b28a2..0a5dfe0 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -677,10 +677,18 @@ void handle_percpu_devid_irq(unsigned int irq, struct irq_desc *desc)
if (chip->irq_ack)
chip->irq_ack(&desc->irq_data);
+ raw_spin_lock(&desc->lock);
+ irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+ raw_spin_unlock(&desc->lock);
+
trace_irq_handler_entry(irq, action);
res = action->handler(irq, dev_id);
trace_irq_handler_exit(irq, action, res);
+ raw_spin_lock(&desc->lock);
+ irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
+ raw_spin_unlock(&desc->lock);
+
if (chip->irq_eoi)
chip->irq_eoi(&desc->irq_data);
}
-------------(2) patch end-----------
Way 2 seems to be needed anyway.
For way 1, I do not find another situation that the gic interrupt states remains active when kernel booting.
And for kdump process, Way 2 is enough.
What do you think about them?
Thanks,
Liu Hua
> Thanks,
>
> M.
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists