• Samuel Holland's avatar
    irqchip/sifive-plic: Separate the enable and mask operations · a1706a1c
    Samuel Holland authored
    The PLIC has two per-IRQ checks before sending an IRQ to a hart context.
    First, it checks that the IRQ's priority is nonzero. Then, it checks
    that the enable bit is set for that combination of IRQ and context.
    
    Currently, the PLIC driver sets both the priority value and the enable
    bit in its (un)mask operations. However, modifying the enable bit is
    problematic for two reasons:
      1) The enable bits are packed, so changes are not atomic and require
         taking a spinlock.
      2) The following requirement from the PLIC spec, which explains the
         racy (un)mask operations in plic_irq_eoi():
    
           If the completion ID does not match an interrupt source
           that is currently enabled for the target, the completion
           is silently ignored.
    
    Both of these problems are solved by using the priority value to mask
    IRQs. Each IRQ has a separate priority register, so writing the priority
    value is atomic. And since the enable bit remains set while an IRQ is
    masked, the EOI operation works normally. The enable bits are still used
    to control the IRQ's affinity.
    Signed-off-by: default avatarSamuel Holland <samuel@sholland.org>
    Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
    Link: https://lore.kernel.org/r/20220701202440.59059-3-samuel@sholland.org
    a1706a1c
irq-sifive-plic.c 12.4 KB