于 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....@huawei.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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to