Changeset 2a103b5 in mainline


Ignore:
Timestamp:
2019-06-09T11:31:38Z (5 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c48de91
Parents:
b401b33
Message:

Introduce PIC operations indirection mechanism

Some architectures switch from one interrupt controller implementation
to another during runtime. By providing a cleaner indirection mechanism,
it is possible e.g. for the ia32 IRQ 7 handler to distinguish i8259
spurious interrupts from actual IRQ 7 device interrupts, even when the
i8259 interrupt controller is no longer active.

Location:
kernel
Files:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/amd64/include/arch/interrupt.h

    rb401b33 r2a103b5  
    8484#define VECTOR_DEBUG_IPI          (IVT_FREEBASE + 2)
    8585
    86 extern void (*disable_irqs_function)(uint16_t);
    87 extern void (*enable_irqs_function)(uint16_t);
    88 extern void (*eoi_function)(unsigned int);
    89 extern const char *irqs_info;
    90 
    9186extern void interrupt_init(void);
    92 extern void trap_virtual_enable_irqs(uint16_t);
    93 extern void trap_virtual_disable_irqs(uint16_t);
    9487
    9588#endif
  • kernel/arch/amd64/src/amd64.c

    rb401b33 r2a103b5  
    6060#include <arch/vreg.h>
    6161#include <arch/kseg.h>
     62#include <genarch/pic/pic_ops.h>
    6263
    6364#ifdef CONFIG_SMP
     
    123124                    (i8259_t *) I8259_PIC1_BASE, IVT_IRQBASE);
    124125
    125                 /*
    126                  * Set the enable/disable IRQs handlers.
    127                  * Set the End-of-Interrupt handler.
    128                  */
    129                 enable_irqs_function = pic_enable_irqs;
    130                 disable_irqs_function = pic_disable_irqs;
    131                 eoi_function = pic_eoi;
    132                 irqs_info = "i8259";
     126                /* Set PIC operations. */
     127                pic_ops = &i8259_pic_ops;
    133128        }
    134129}
     
    209204                        indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
    210205                        i8042_wire(i8042_instance, kbrd);
    211                         trap_virtual_enable_irqs(1 << IRQ_KBD);
    212                         trap_virtual_enable_irqs(1 << IRQ_MOUSE);
     206                        pic_ops->enable_irqs(1 << IRQ_KBD);
     207                        pic_ops->enable_irqs(1 << IRQ_MOUSE);
    213208                }
    214209        }
     
    235230                        indev_t *srln = srln_wire(srln_instance, sink);
    236231                        ns16550_wire(ns16550_instance, srln);
    237                         trap_virtual_enable_irqs(1 << IRQ_NS16550);
     232                        pic_ops->enable_irqs(1 << IRQ_NS16550);
    238233                }
    239234#endif
     
    246241#endif
    247242
    248         if (irqs_info != NULL)
    249                 sysinfo_set_item_val(irqs_info, NULL, true);
     243        sysinfo_set_item_val(pic_ops->get_name(), NULL, true);
    250244}
    251245
  • kernel/arch/amd64/src/interrupt.c

    rb401b33 r2a103b5  
    3838#include <panic.h>
    3939#include <genarch/drivers/i8259/i8259.h>
     40#include <genarch/pic/pic_ops.h>
    4041#include <halt.h>
    4142#include <cpu.h>
     
    5758 * Interrupt and exception dispatching.
    5859 */
    59 
    60 void (*disable_irqs_function)(uint16_t irqmask) = NULL;
    61 void (*enable_irqs_function)(uint16_t irqmask) = NULL;
    62 void (*eoi_function)(unsigned int) = NULL;
    63 const char *irqs_info = NULL;
     60pic_ops_t *pic_ops = NULL;
    6461
    6562void istate_decode(istate_t *istate)
     
    8986            "r14=%0#18" PRIx64 "\tr15=%0#18" PRIx64 "\n",
    9087            istate->r12, istate->r13, istate->r14, istate->r15);
    91 }
    92 
    93 static void trap_virtual_eoi(unsigned int irq)
    94 {
    95         if (eoi_function)
    96                 eoi_function(irq);
    97         else
    98                 panic("No eoi_function.");
    99 
    10088}
    10189
     
    157145static void tlb_shootdown_ipi(unsigned int n, istate_t *istate)
    158146{
    159         trap_virtual_eoi(0);
     147        pic_ops->eoi(0);
    160148        tlb_shootdown_ipi_recv();
    161149}
     
    182170                if (irq->preack) {
    183171                        /* Send EOI before processing the interrupt */
    184                         trap_virtual_eoi(inum);
     172                        pic_ops->eoi(inum);
    185173                        ack = true;
    186174                }
     
    195183
    196184        if (!ack)
    197                 trap_virtual_eoi(inum);
     185                pic_ops->eoi(inum);
    198186}
    199187
     
    201189{
    202190        unsigned int inum = n - IVT_IRQBASE;
    203         if (!pic_is_spurious(inum)) {
     191        if (!pic_ops->is_spurious(inum)) {
    204192                /* This is actually not a spurious IRQ, so proceed as usual. */
    205193                irq_interrupt(n, istate);
    206194                return;
    207195        }
    208         pic_handle_spurious(n);
     196        pic_ops->handle_spurious(n);
    209197#ifdef CONFIG_DEBUG
    210198        log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt %u", CPU->id,
     
    242230}
    243231
    244 void trap_virtual_enable_irqs(uint16_t irqmask)
    245 {
    246         if (enable_irqs_function)
    247                 enable_irqs_function(irqmask);
    248         else
    249                 panic("No enable_irqs_function.");
    250 }
    251 
    252 void trap_virtual_disable_irqs(uint16_t irqmask)
    253 {
    254         if (disable_irqs_function)
    255                 disable_irqs_function(irqmask);
    256         else
    257                 panic("No disable_irqs_function.");
    258 }
    259 
    260232/** @}
    261233 */
  • kernel/arch/ia32/include/arch/interrupt.h

    rb401b33 r2a103b5  
    8888#define VECTOR_DEBUG_IPI          (IVT_FREEBASE + 2)
    8989
    90 extern void (*disable_irqs_function)(uint16_t);
    91 extern void (*enable_irqs_function)(uint16_t);
    92 extern void (*eoi_function)(unsigned int);
    93 extern const char *irqs_info;
    94 
    9590extern void interrupt_init(void);
    96 extern void trap_virtual_enable_irqs(uint16_t);
    97 extern void trap_virtual_disable_irqs(uint16_t);
    9891
    9992#endif
  • kernel/arch/ia32/include/arch/smp/apic.h

    rb401b33 r2a103b5  
    4343#include <cpu.h>
    4444#include <stdint.h>
     45#include <genarch/pic/pic_ops.h>
    4546
    4647#define FIXED  (0 << 0)
     
    347348} io_apic_id_t;
    348349
     350extern pic_ops_t apic_pic_ops;
     351
    349352extern volatile uint32_t *l_apic;
    350353extern volatile uint32_t *io_apic;
  • kernel/arch/ia32/src/drivers/i8254.c

    rb401b33 r2a103b5  
    9696{
    9797        pio_write_8(CLK_PORT4, 0x36);
    98         pic_disable_irqs(1 << IRQ_CLK);
     98        i8259_disable_irqs(1 << IRQ_CLK);
    9999        pio_write_8(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
    100100        pio_write_8(CLK_PORT1, (CLK_CONST / HZ) >> 8);
    101         pic_enable_irqs(1 << IRQ_CLK);
     101        i8259_enable_irqs(1 << IRQ_CLK);
    102102}
    103103
  • kernel/arch/ia32/src/ia32.c

    rb401b33 r2a103b5  
    5858#include <genarch/multiboot/multiboot.h>
    5959#include <genarch/multiboot/multiboot2.h>
     60#include <genarch/pic/pic_ops.h>
    6061#include <arch/pm.h>
    6162#include <arch/vreg.h>
     
    112113                    (i8259_t *) I8259_PIC1_BASE, IVT_IRQBASE);
    113114
    114                 /*
    115                  * Set the enable/disable IRQs handlers.
    116                  * Set the End-of-Interrupt handler.
    117                  */
    118                 enable_irqs_function = pic_enable_irqs;
    119                 disable_irqs_function = pic_disable_irqs;
    120                 eoi_function = pic_eoi;
    121                 irqs_info = "i8259";
     115                /* Set PIC operations. */
     116                pic_ops = &i8259_pic_ops;
    122117        }
    123118}
     
    194189                        indev_t *kbrd = kbrd_wire(kbrd_instance, sink);
    195190                        i8042_wire(i8042_instance, kbrd);
    196                         trap_virtual_enable_irqs(1 << IRQ_KBD);
    197                         trap_virtual_enable_irqs(1 << IRQ_MOUSE);
     191                        pic_ops->enable_irqs(1 << IRQ_KBD);
     192                        pic_ops->enable_irqs(1 << IRQ_MOUSE);
    198193                }
    199194        }
     
    220215                        indev_t *srln = srln_wire(srln_instance, sink);
    221216                        ns16550_wire(ns16550_instance, srln);
    222                         trap_virtual_enable_irqs(1 << IRQ_NS16550);
     217                        pic_ops->enable_irqs(1 << IRQ_NS16550);
    223218                }
    224219#endif
     
    231226#endif
    232227
    233         if (irqs_info != NULL)
    234                 sysinfo_set_item_val(irqs_info, NULL, true);
     228        sysinfo_set_item_val(pic_ops->get_name(), NULL, true);
    235229}
    236230
  • kernel/arch/ia32/src/interrupt.c

    rb401b33 r2a103b5  
    4040#include <panic.h>
    4141#include <genarch/drivers/i8259/i8259.h>
     42#include <genarch/pic/pic_ops.h>
    4243#include <halt.h>
    4344#include <cpu.h>
     
    6162 */
    6263
    63 void (*disable_irqs_function)(uint16_t irqmask) = NULL;
    64 void (*enable_irqs_function)(uint16_t irqmask) = NULL;
    65 void (*eoi_function)(unsigned int) = NULL;
    66 const char *irqs_info = NULL;
     64pic_ops_t *pic_ops = NULL;
    6765
    6866void istate_decode(istate_t *istate)
     
    8886            istate_from_uspace(istate) ? istate->esp :
    8987            (uint32_t) &istate->esp);
    90 }
    91 
    92 static void trap_virtual_eoi(unsigned int inum)
    93 {
    94         if (eoi_function)
    95                 eoi_function(inum);
    96         else
    97                 panic("No eoi_function.");
    98 
    9988}
    10089
     
    179168    istate_t *istate __attribute__((unused)))
    180169{
    181         trap_virtual_eoi(0);
     170        pic_ops->eoi(0);
    182171        tlb_shootdown_ipi_recv();
    183172}
     
    202191                if (irq->preack) {
    203192                        /* Send EOI before processing the interrupt */
    204                         trap_virtual_eoi(inum);
     193                        pic_ops->eoi(inum);
    205194                        ack = true;
    206195                }
     
    215204
    216205        if (!ack)
    217                 trap_virtual_eoi(inum);
     206                pic_ops->eoi(inum);
    218207}
    219208
     
    221210{
    222211        unsigned int inum = n - IVT_IRQBASE;
    223         if (!pic_is_spurious(inum)) {
     212        if (!pic_ops->is_spurious(inum)) {
    224213                /* This is actually not a spurious IRQ, so proceed as usual. */
    225214                irq_interrupt(n, istate);
    226215                return;
    227216        }
    228         pic_handle_spurious(n);
     217        pic_ops->handle_spurious(n);
    229218#ifdef CONFIG_DEBUG
    230219        log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt %u", CPU->id,
     
    264253}
    265254
    266 void trap_virtual_enable_irqs(uint16_t irqmask)
    267 {
    268         if (enable_irqs_function)
    269                 enable_irqs_function(irqmask);
    270         else
    271                 panic("No enable_irqs_function.");
    272 }
    273 
    274 void trap_virtual_disable_irqs(uint16_t irqmask)
    275 {
    276         if (disable_irqs_function)
    277                 disable_irqs_function(irqmask);
    278         else
    279                 panic("No disable_irqs_function.");
    280 }
    281 
    282255/** @}
    283256 */
  • kernel/arch/ia32/src/smp/apic.c

    rb401b33 r2a103b5  
    4747#include <arch.h>
    4848#include <ddi/irq.h>
     49#include <genarch/pic/pic_ops.h>
    4950
    5051#ifdef CONFIG_SMP
     
    6364 */
    6465
     66static const char *apic_get_name(void);
     67static bool l_apic_is_spurious(unsigned int);
     68static void l_apic_handle_spurious(unsigned int);
     69
     70pic_ops_t apic_pic_ops = {
     71        .get_name = apic_get_name,
     72        .enable_irqs = io_apic_enable_irqs,
     73        .disable_irqs = io_apic_disable_irqs,
     74        .eoi = l_apic_eoi,
     75        .is_spurious = l_apic_is_spurious,
     76        .handle_spurious = l_apic_handle_spurious,
     77};
     78
    6579/*
    6680 * These variables either stay configured as initilalized, or are changed by
     
    125139#endif /* LAPIC_VERBOSE */
    126140
     141const char *apic_get_name(void)
     142{
     143        return "apic";
     144}
     145
     146bool l_apic_is_spurious(unsigned int n)
     147{
     148        return n == VECTOR_APIC_SPUR;
     149}
     150
     151void l_apic_handle_spurious(unsigned int n)
     152{
     153}
     154
    127155/** APIC spurious interrupt handler.
    128156 *
     
    134162    istate_t *istate __attribute__((unused)))
    135163{
    136 #ifdef CONFIG_DEBUG
    137         log(LF_ARCH, LVL_DEBUG, "cpu%u: APIC spurious interrupt", CPU->id);
    138 #endif
    139164}
    140165
     
    175200            (iroutine_t) apic_spurious);
    176201
    177         enable_irqs_function = io_apic_enable_irqs;
    178         disable_irqs_function = io_apic_disable_irqs;
    179         eoi_function = l_apic_eoi;
    180         irqs_info = "apic";
     202        pic_ops = &apic_pic_ops;
    181203
    182204        /*
  • kernel/arch/ia32/src/smp/smp.c

    rb401b33 r2a103b5  
    130130        pio_write_8((ioport8_t *) 0x71, 0xa);
    131131
    132         pic_disable_irqs(0xffff);
     132        i8259_disable_irqs(0xffff);
    133133        apic_init();
    134134
  • kernel/arch/ia64/include/arch/interrupt.h

    rb401b33 r2a103b5  
    9292extern void disabled_fp_register(unsigned int, istate_t *);
    9393
    94 extern void trap_virtual_enable_irqs(uint16_t);
    95 
    9694void exception_init(void);
    9795#endif
  • kernel/arch/ia64/src/interrupt.c

    rb401b33 r2a103b5  
    301301}
    302302
    303 void trap_virtual_enable_irqs(uint16_t irqmask)
    304 {
    305 }
    306 
    307303void exception_init(void)
    308304{
  • kernel/arch/mips32/src/mach/malta/malta.c

    rb401b33 r2a103b5  
    7575{
    7676        uint8_t isa_irq = host2uint32_t_le(pio_read_32(GT64120_PCI0_INTACK));
    77         if (pic_is_spurious(isa_irq)) {
    78                 pic_handle_spurious(isa_irq);
     77        if (i8259_is_spurious(isa_irq)) {
     78                i8259_handle_spurious(isa_irq);
    7979#ifdef CONFIG_DEBUG
    8080                log(LF_ARCH, LVL_DEBUG, "cpu%u: PIC spurious interrupt %u",
     
    9393#endif
    9494        }
    95         pic_eoi(isa_irq);
     95        i8259_eoi(isa_irq);
    9696}
    9797
     
    146146                        indev_t *srln = srln_wire(srln_instance, sink);
    147147                        ns16550_wire(tty_instance, srln);
    148                         pic_enable_irqs(1 << TTY_ISA_IRQ);
     148                        i8259_enable_irqs(1 << TTY_ISA_IRQ);
    149149                }
    150150        }
  • kernel/genarch/include/genarch/drivers/i8259/i8259.h

    rb401b33 r2a103b5  
    3838#include <typedefs.h>
    3939#include <arch/interrupt.h>
     40#include <genarch/pic/pic_ops.h>
    4041#include <stdbool.h>
    4142
     
    6263} __attribute__((packed)) i8259_t;
    6364
     65extern pic_ops_t i8259_pic_ops;
     66
    6467extern void i8259_init(i8259_t *, i8259_t *, unsigned int);
    65 extern void pic_enable_irqs(uint16_t);
    66 extern void pic_disable_irqs(uint16_t);
    67 extern void pic_eoi(unsigned int);
    68 extern bool pic_is_spurious(unsigned int);
    69 extern void pic_handle_spurious(unsigned int);
     68extern void i8259_enable_irqs(uint16_t);
     69extern void i8259_disable_irqs(uint16_t);
     70extern void i8259_eoi(unsigned int);
     71extern bool i8259_is_spurious(unsigned int);
     72extern void i8259_handle_spurious(unsigned int);
    7073
    7174#endif
  • kernel/genarch/src/drivers/i8259/i8259.c

    rb401b33 r2a103b5  
    4343#include <interrupt.h>
    4444
     45static const char *i8259_get_name(void);
     46
     47pic_ops_t i8259_pic_ops = {
     48        .get_name = i8259_get_name,
     49        .enable_irqs = i8259_enable_irqs,
     50        .disable_irqs = i8259_disable_irqs,
     51        .eoi = i8259_eoi,
     52        .is_spurious = i8259_is_spurious,
     53        .handle_spurious = i8259_handle_spurious
     54};
     55
    4556// XXX: need to change pic_* API to get rid of these
    4657static i8259_t *saved_pic0;
     
    7687        pio_write_8(&pic1->port2, 1);
    7788
    78         pic_disable_irqs(0xffff);               /* disable all irq's */
    79         pic_enable_irqs(1 << PIC0_IRQ_PIC1);    /* but enable PIC0_IRQ_PIC1 */
     89        i8259_disable_irqs(0xffff);             /* disable all irq's */
     90        i8259_enable_irqs(1 << PIC0_IRQ_PIC1);  /* but enable PIC0_IRQ_PIC1 */
    8091}
    8192
    82 void pic_enable_irqs(uint16_t irqmask)
     93const char *i8259_get_name(void)
     94{
     95        return "i8259";
     96}
     97
     98void i8259_enable_irqs(uint16_t irqmask)
    8399{
    84100        uint8_t x;
     
    96112}
    97113
    98 void pic_disable_irqs(uint16_t irqmask)
     114void i8259_disable_irqs(uint16_t irqmask)
    99115{
    100116        uint8_t x;
     
    112128}
    113129
    114 void pic_eoi(unsigned int irq)
     130void i8259_eoi(unsigned int irq)
    115131{
    116132        if (irq >= PIC0_IRQ_COUNT)
     
    119135}
    120136
    121 bool pic_is_spurious(unsigned int irq)
     137bool i8259_is_spurious(unsigned int irq)
    122138{
    123139        pio_write_8(&saved_pic0->port1, PIC_OCW3 | PIC_OCW3_READ_ISR);
     
    128144}
    129145
    130 void pic_handle_spurious(unsigned int irq)
     146void i8259_handle_spurious(unsigned int irq)
    131147{
    132148        /* For spurious IRQs from pic1, we need to isssue an EOI to pic0 */
Note: See TracChangeset for help on using the changeset viewer.