AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
irq.c File Reference

x86: devices' interrupts (IRQs), whichever controller brings them: the 8259s or the APIC, each an x86_irq_chip. More...

#include <core/system.h>
#include <core/arch.h>
#include <core/panic.h>
#include <core/string.h>
#include <cpu/cpu.h>
#include <dev/irq.h>
#include <platform/misc.h>
#include <sys/sched.h>
#include <sys/signal.h>
#include <sys/lock.h>
#include <mm/pmap.h>

Go to the source code of this file.

Data Structures

struct  handler
 An installed handler, on its interrupt's list. More...
struct  [struct].irqs

Functions

static struct x86_irq_chip * chip_of (unsigned irq)
 Returns the controller of an IRQ: its own, or the system's.
void x86_irq_chip_set (struct x86_irq_chip *c)
 Sets the system's interrupt controller.
const char * x86_irq_chip_name (void)
 Returns the name of the system's interrupt controller.
void x86_irq_alloc_from (unsigned first)
 Sets the first IRQ that x86_irq_alloc() may give: past the I/O APICs' last pin.
int x86_irq_alloc (struct x86_irq_chip *c)
 Gives a free IRQ with a controller of its own, for an MSI.
int irq_install (unsigned irq, irq_handler_t fn, void *arg)
 Installs a handler for an IRQ.
void irq_uninstall (unsigned irq, irq_handler_t fn, void *arg)
 Removes a handler that irq_install() installed.
void x86_irq_tick_switch (void)
 Asks for a thread switch once the current interrupt is done: the tick calls it.
static void irq_handle (struct x86_regs *r)
 Runs an interrupt's handlers, then tells its controller that it is done.
static void irq_dispatch (struct x86_regs *r)
 Handles an interrupt, then switches threads if the tick asked for it or an urgent thread was woken, and returns to what was interrupted.
void __x86_irq_handler (struct x86_regs *r)
 Handles an interrupt: a device's, the tick, or an IPI.
void x86_irq_gates_setup (void)
 Sets the IDT's gates for the interrupts: vectors 32 to 79, the local APIC's timer, the TLB and wake IPIs, and its spurious interrupt.
int arch_interrupts_info (char *buf, size_t size)
 Writes /proc/interrupts: the controller, then how many times each IRQ with handlers came, and how many TLB flushes each CPU did for another.

Variables

static struct  irqs [X86_IRQ_NR]
static struct x86_irq_chip * chip
static unsigned alloc_first = X86_IRQ_TIMER

Detailed Description

x86: devices' interrupts (IRQs), whichever controller brings them: the 8259s or the APIC, each an x86_irq_chip.

IRQ n is vector 32 + n. With the 8259s, the IRQs are the ISA bus's 16. With the APIC, they are what the I/O APICs route from their pins: the ISA IRQs too (on the pins the MADT says), and PCI devices' lines (from their configuration space). The local APIC's timer, vector 240, is an IRQ of its own here (X86_IRQ_TIMER).

An IRQ may have several handlers, because a PCI line can be shared: each is called, and each looks at its own device. An IRQ may also have a controller of its own: an MSI's is the device itself (x86_irq_alloc() gives those IRQs, above the I/O APICs' pins).

After the handlers, the controller is told that the interrupt is done (the EOI; a level-triggered line would raise it again before). Only then may what the interrupt woke up run (an urgent thread, or the thread switch the tick asked for).

Definition in file irq.c.

Function Documentation

◆ __x86_irq_handler()

void __x86_irq_handler ( struct x86_regs * r)

Handles an interrupt: a device's, the tick, or an IPI.

The stubs in cpu.S call it. It takes the kernel lock if it came from user mode or the idle loop (in the kernel, the lock is held already), and lets go of it on the way back. The TLB IPI is handled without the lock, because the CPU that sent it holds it, waiting.

Parameters
rthe interrupted registers, saved on the kernel stack

Definition at line 237 of file irq.c.

References __x86_irq_handler(), curthread, irq_dispatch(), irq_handle(), kernel_enter(), kernel_leave(), sched_thread_killed(), x86_regs::vec, x86_lapic_eoi(), x86_lapic_timer_cpu_start(), x86_tlb_ipi(), X86_TLB_VECTOR, and X86_WAKE_VECTOR.

Referenced by __x86_irq_handler().

◆ arch_interrupts_info()

int arch_interrupts_info ( char * buf,
size_t size )

Writes /proc/interrupts: the controller, then how many times each IRQ with handlers came, and how many TLB flushes each CPU did for another.

Parameters
bufwhere to write it
sizethe buffer's size
Returns
the length of the text

Definition at line 310 of file irq.c.

References arch_interrupts_info(), chip, chip_of(), cpus, cpus_count, x86_irq_chip::describe, handlers, irqs, snprintf(), x86_irq_chip::timer, x86_irq_chip_name(), X86_IRQ_NR, and X86_IRQ_TIMER.

◆ chip_of()

struct x86_irq_chip * chip_of ( unsigned irq)
static

Returns the controller of an IRQ: its own, or the system's.

Definition at line 57 of file irq.c.

References chip, chip_of(), and irqs.

Referenced by arch_interrupts_info(), chip_of(), irq_handle(), irq_install(), and irq_uninstall().

◆ irq_dispatch()

void irq_dispatch ( struct x86_regs * r)
static

Handles an interrupt, then switches threads if the tick asked for it or an urgent thread was woken, and returns to what was interrupted.

Definition at line 197 of file irq.c.

References x86_regs::cs, curthread, irq_dispatch(), irq_handle(), sched_idle_wakeup(), sched_urgent, schedule(), and x86_return_to_user().

Referenced by __x86_irq_handler(), and irq_dispatch().

◆ irq_handle()

void irq_handle ( struct x86_regs * r)
static

Runs an interrupt's handlers, then tells its controller that it is done.

Definition at line 176 of file irq.c.

References chip, chip_of(), x86_irq_chip::eoi, handlers, irq_handle(), irqs, x86_regs::vec, X86_IRQ_NR, X86_IRQ_TIMER, and X86_TIMER_VECTOR.

◆ irq_install()

int irq_install ( unsigned irq,
irq_handler_t fn,
void * arg )

Installs a handler for an IRQ.

The first handler installed unmasks the IRQ at its interrupt controller.

Parameters
irqthe IRQ, the platform's number for it
fnthe handler
argthe argument the handler is called with
Returns
0, -EINVAL if there's no such IRQ, or -ENOMEM if there was no memory for the handler

Definition at line 115 of file irq.c.

References handler::arg, chip_of(), handler::fn, irq_install(), irqs, kmalloc(), M_ZERO, handler::next, x86_irq_chip::unmask, X86_IRQ_NR, and X86_IRQ_TIMER.

◆ irq_uninstall()

void irq_uninstall ( unsigned irq,
irq_handler_t fn,
void * arg )

Removes a handler that irq_install() installed.

The last handler removed masks the IRQ at its interrupt controller.

Parameters
irqthe IRQ
fnthe handler, as it was installed
argits argument, as it was installed

Definition at line 147 of file irq.c.

References handler::arg, chip_of(), handler::fn, handlers, irq_uninstall(), irqs, kfree(), x86_irq_chip::mask, handler::next, X86_IRQ_NR, and X86_IRQ_TIMER.

◆ x86_irq_alloc()

int x86_irq_alloc ( struct x86_irq_chip * c)

Gives a free IRQ with a controller of its own, for an MSI.

Parameters
cthe IRQ's controller
Returns
the IRQ, or -1 if there's no free one

Definition at line 99 of file irq.c.

References alloc_first, chip, handlers, irqs, x86_irq_alloc(), and X86_IRQ_TIMER.

Referenced by arch_msi_alloc(), and x86_irq_alloc().

◆ x86_irq_alloc_from()

void x86_irq_alloc_from ( unsigned first)

Sets the first IRQ that x86_irq_alloc() may give: past the I/O APICs' last pin.

Parameters
firstthe first IRQ

Definition at line 88 of file irq.c.

References alloc_first, and x86_irq_alloc_from().

Referenced by x86_apic_setup(), and x86_irq_alloc_from().

◆ x86_irq_chip_name()

const char * x86_irq_chip_name ( void )

Returns the name of the system's interrupt controller.

Returns
its name, or "none"

Definition at line 77 of file irq.c.

References chip, x86_irq_chip::name, and x86_irq_chip_name().

Referenced by arch_interrupts_info(), x86_irq_chip_name(), and x86_pc_irq_init().

◆ x86_irq_chip_set()

void x86_irq_chip_set ( struct x86_irq_chip * c)

Sets the system's interrupt controller.

Parameters
cthe controller: the 8259s or the APIC

Definition at line 67 of file irq.c.

References chip, and x86_irq_chip_set().

Referenced by x86_apic_setup(), x86_irq_chip_set(), and x86_pc_irq_init().

◆ x86_irq_gates_setup()

void x86_irq_gates_setup ( void )

Sets the IDT's gates for the interrupts: vectors 32 to 79, the local APIC's timer, the TLB and wake IPIs, and its spurious interrupt.

Definition at line 266 of file irq.c.

References x86_idt_gate_set(), x86_irq_gates_setup(), X86_SPURIOUS_VECTOR, X86_TIMER_VECTOR, X86_TLB_VECTOR, and X86_WAKE_VECTOR.

Referenced by x86_irq_gates_setup(), and x86_pc_irq_init().

◆ x86_irq_tick_switch()

void x86_irq_tick_switch ( void )

Asks for a thread switch once the current interrupt is done: the tick calls it.

Definition at line 169 of file irq.c.

References x86_irq_tick_switch().

Referenced by x86_irq_tick_switch(), and x86_sched_handler().

Variable Documentation

◆ alloc_first

unsigned alloc_first = X86_IRQ_TIMER
static

Definition at line 54 of file irq.c.

Referenced by x86_irq_alloc(), and x86_irq_alloc_from().

◆ chip

struct x86_irq_chip* chip
static

◆ irqs