Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset fd67c9f in mainline


Ignore:
Timestamp:
2019-04-06T08:10:27Z (22 months ago)
Author:
Jakub Jermar <jakub@…>
Branches:
master
Children:
534bcdf
Parents:
ef56a43
Message:

Handle PIC spurious IRQs with care

Location:
kernel
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/src/interrupt.c

    ref56a43 rfd67c9f  
    172172        bool ack = false;
    173173        assert(inum < IRQ_COUNT);
    174         assert(inum != IRQ_PIC0_SPUR);
    175         assert(inum != IRQ_PIC1_SPUR);
    176174        assert(inum != IRQ_PIC1);
    177175
     
    190188                irq_spinlock_unlock(&irq->lock, false);
    191189        } else {
    192                 /*
    193                  * Spurious interrupt.
    194                  */
    195190#ifdef CONFIG_DEBUG
    196                 log(LF_ARCH, LVL_DEBUG, "cpu%u: spurious interrupt (inum=%u)",
    197                     CPU->id, inum);
     191                log(LF_ARCH, LVL_DEBUG, "cpu%u: unhandled IRQ %u", CPU->id,
     192                    inum);
    198193#endif
    199194        }
     
    205200static void pic_spurious(unsigned int n, istate_t *istate)
    206201{
    207         /*
    208          * XXX: Examine ISR to figure out whether this is indeed a spurious
    209          *      or actual IRQ.
    210          */
     202        unsigned int inum = n - IVT_IRQBASE;
     203        if (!pic_is_spurious(inum)) {
     204                /* This is actually not a spurious IRQ, so proceed as usual. */
     205                irq_interrupt(n, istate);
     206                return;
     207        }
     208        pic_handle_spurious(n);
    211209#ifdef CONFIG_DEBUG
    212         log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt", CPU->id);
     210        log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt %u", CPU->id,
     211            inum);
    213212#endif
    214213}
  • kernel/arch/ia32/src/interrupt.c

    ref56a43 rfd67c9f  
    192192        bool ack = false;
    193193        assert(inum < IRQ_COUNT);
    194         assert(inum != IRQ_PIC0_SPUR);
    195         assert(inum != IRQ_PIC1_SPUR);
    196194        assert(inum != IRQ_PIC1);
    197195
     
    210208                irq_spinlock_unlock(&irq->lock, false);
    211209        } else {
    212                 /*
    213                  * Spurious interrupt.
    214                  */
    215210#ifdef CONFIG_DEBUG
    216                 printf("cpu%u: spurious interrupt (inum=%u)\n", CPU->id, inum);
     211                log(LF_ARCH, LVL_DEBUG, "cpu%u: unhandled IRQ %u", CPU->id,
     212                    inum);
    217213#endif
    218214        }
     
    224220static void pic_spurious(unsigned int n, istate_t *istate)
    225221{
    226         /*
    227          * XXX: Examine ISR to figure out whether this is indeed a spurious
    228          *      or actual IRQ.
    229          */
     222        unsigned int inum = n - IVT_IRQBASE;
     223        if (!pic_is_spurious(inum)) {
     224                /* This is actually not a spurious IRQ, so proceed as usual. */
     225                irq_interrupt(n, istate);
     226                return;
     227        }
     228        pic_handle_spurious(n);
    230229#ifdef CONFIG_DEBUG
    231         log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt", CPU->id);
     230        log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt %u", CPU->id,
     231            inum);
    232232#endif
    233233}
  • kernel/arch/mips32/include/arch/mach/malta/malta.h

    ref56a43 rfd67c9f  
    4545
    4646#define PIC0_BASE               (MALTA_PCI_BASE + 0x20)
    47 #define PIC0_SPURIOUS_IRQ       7
    4847#define PIC1_BASE               (MALTA_PCI_BASE + 0xa0)
    49 #define PIC1_SPURIOUS_IRQ       15
    5048
    5149#define ISA_IRQ_COUNT           16
  • kernel/arch/mips32/src/mach/malta/malta.c

    ref56a43 rfd67c9f  
    7474{
    7575        uint8_t isa_irq = host2uint32_t_le(pio_read_32(GT64120_PCI0_INTACK));
    76         if (isa_irq == PIC0_SPURIOUS_IRQ || isa_irq == PIC1_SPURIOUS_IRQ) {
    77                 /*
    78                  * XXX: Examine ISR to figure out whether this is indeed a
    79                  *      spurious or actual IRQ.
    80                  */
     76        if (pic_is_spurious(isa_irq)) {
     77                pic_handle_spurious(isa_irq);
    8178#ifdef CONFIG_DEBUG
    82                 log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt",
    83                     CPU->id);
     79                log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt %u",
     80                    CPU->id, isa_irq);
    8481                return;
    8582#endif
     
    9188        } else {
    9289#ifdef CONFIG_DEBUG
    93                 log(LF_ARCH, LVL_DEBUG, "cpu%u: spurious IRQ (irq=%u)",
     90                log(LF_ARCH, LVL_DEBUG, "cpu%u: unhandled IRQ (irq=%u)",
    9491                    CPU->id, isa_irq);
    9592#endif
  • kernel/genarch/include/genarch/drivers/i8259/i8259.h

    ref56a43 rfd67c9f  
    3838#include <typedefs.h>
    3939#include <arch/interrupt.h>
     40#include <stdbool.h>
    4041
    4142/* ICW1 bits */
     
    4344#define PIC_ICW1_NEEDICW4  (1 << 0)
    4445
     46/* OCW3 bits */
     47#define PIC_OCW3           (1 << 3)
     48#define PIC_OCW3_READ_ISR  (3 << 0)
     49
    4550/* OCW4 bits */
    4651#define PIC_OCW4           (0 << 3)
    4752#define PIC_OCW4_NSEOI     (1 << 5)
     53
     54#define PIC_IRQ_COUNT      8
     55#define PIC_SPURIOUS_IRQ   7
    4856
    4957typedef struct {
     
    5664extern void pic_disable_irqs(uint16_t);
    5765extern void pic_eoi(unsigned int);
     66extern bool pic_is_spurious(unsigned int);
     67extern void pic_handle_spurious(unsigned int);
    5868
    5969#endif
  • kernel/genarch/src/drivers/i8259/i8259.c

    ref56a43 rfd67c9f  
    9090                    (uint8_t) (x & (~(irqmask & 0xff))));
    9191        }
    92         if (irqmask >> 8) {
     92        if (irqmask >> PIC_IRQ_COUNT) {
    9393                x = pio_read_8(&saved_pic1->port2);
    9494                pio_write_8(&saved_pic1->port2,
    95                     (uint8_t) (x & (~(irqmask >> 8))));
     95                    (uint8_t) (x & (~(irqmask >> PIC_IRQ_COUNT))));
    9696        }
    9797}
     
    106106                    (uint8_t) (x | (irqmask & 0xff)));
    107107        }
    108         if (irqmask >> 8) {
     108        if (irqmask >> PIC_IRQ_COUNT) {
    109109                x = pio_read_8(&saved_pic1->port2);
    110                 pio_write_8(&saved_pic1->port2, (uint8_t) (x | (irqmask >> 8)));
     110                pio_write_8(&saved_pic1->port2,
     111                    (uint8_t) (x | (irqmask >> PIC_IRQ_COUNT)));
    111112        }
    112113}
     
    114115void pic_eoi(unsigned int irq)
    115116{
    116         if (irq >= 8)
     117        if (irq >= PIC_IRQ_COUNT)
    117118                pio_write_8(&saved_pic1->port1, PIC_OCW4 | PIC_OCW4_NSEOI);
    118119        pio_write_8(&saved_pic0->port1, PIC_OCW4 | PIC_OCW4_NSEOI);
    119120}
    120121
     122bool pic_is_spurious(unsigned int irq)
     123{
     124        pio_write_8(&saved_pic0->port1, PIC_OCW3 | PIC_OCW3_READ_ISR);
     125        pio_write_8(&saved_pic1->port1, PIC_OCW3 | PIC_OCW3_READ_ISR);
     126        uint8_t isr_lo = pio_read_8(&saved_pic0->port1);
     127        uint8_t isr_hi = pio_read_8(&saved_pic1->port1);
     128        return !(((isr_hi << PIC_IRQ_COUNT) | isr_lo) & (1 << irq));
     129}
     130
     131void pic_handle_spurious(unsigned int irq)
     132{
     133        /* For spurious IRQs from pic1, we need to isssue an EOI to pic0 */
     134        if (irq >= PIC_IRQ_COUNT)
     135                pio_write_8(&saved_pic0->port1, PIC_OCW4 | PIC_OCW4_NSEOI);
     136}
     137
    121138/** @}
    122139 */
Note: See TracChangeset for help on using the changeset viewer.