PatchworkOS  c9fea19
A non-POSIX operating system.
Loading...
Searching...
No Matches
IRQ

Interrupt Requests (IRQs) More...

Collaboration diagram for IRQ:

Detailed Description

Interrupt Requests (IRQs)

The IRQ system is responsible for managing external interrupts in the system (as in vectors [VECTOR_EXTERNAL_START, VECTOR_EXTERNAL_END)), where the hardware trigger a physical IRQ (irq_phys_t) which is then mapped to a virtual IRQ (irq_virt_t) using a irq_chip_t.

Physical vs Virtual IRQs

The IRQ chips are usually implemented in a driver and they are responsible for the actual physical to virtual mapping.

Note that physical to virtual mapping might not be 1:1 and that there could be multiple irq_chip_ts in the system.

So, for example, say we receive a physical IRQ 1, which is usually the ps2 keyboard interrupt. Lets also say we have a single IRQ chip, the IOAPIC, which is configured to map physical IRQ 1 to virtual IRQ 0x21 on CPU 0. We would then see all handlers registered for virtual IRQ 0x21 being called on CPU 0.

Todo:
Currently, this system is still simplistic. For example, it cant handle trees of IRQ chips, or multiple chips handling the same physical IRQs. This should be fixed in the future as needed.

Data Structures

struct  irq_func_data_t
 Data passed to IRQ functions. More...
 
struct  irq_handler_t
 Structure to hold an IRQ function and its data. More...
 
struct  irq_t
 IRQ structure. More...
 
struct  irq_domain_t
 IRQ domain structure. More...
 
struct  irq_chip_t
 IRQ chip structure. More...
 

Macros

#define IRQ_PHYS_NONE   UINT32_MAX
 Constant representing no physical IRQ.
 
#define IRQ_INVOKE(virt)   asm volatile("int %0" : : "i"(virt));
 Invoke the given virtual IRQ.
 

Typedefs

typedef uint32_t irq_phys_t
 Physical IRQ numbers.
 
typedef uint8_t irq_virt_t
 Virtual IRQ numbers.
 
typedef void(* irq_func_t) (irq_func_data_t *data)
 Callback function type for IRQs.
 

Enumerations

enum  irq_flags_t {
  IRQ_POLARITY_HIGH = 0 << 0 , IRQ_POLARITY_LOW = 1 << 0 , IRQ_TRIGGER_LEVEL = 0 << 1 , IRQ_TRIGGER_EDGE = 1 << 1 ,
  IRQ_EXCLUSIVE = 0 << 2 , IRQ_SHARED = 1 << 2
}
 IRQ flags. More...
 

Functions

void irq_init (void)
 Initialize the IRQ subsystem.
 
void irq_dispatch (interrupt_frame_t *frame, cpu_t *self)
 Dispatch an IRQ.
 
uint64_t irq_virt_alloc (irq_virt_t *out, irq_phys_t phys, irq_flags_t flags, cpu_t *cpu)
 Allocate a virtual IRQ mapped to the given physical IRQ.
 
void irq_virt_free (irq_virt_t virt)
 Free a previously allocated virtual IRQ.
 
uint64_t irq_virt_set_affinity (irq_virt_t virt, cpu_t *cpu)
 Change the CPU responsible for an IRQ.
 
uint64_t irq_chip_register (irq_chip_t *chip, irq_phys_t start, irq_phys_t end, void *private)
 Register an IRQ chip for a range of physical IRQs.
 
void irq_chip_unregister (irq_chip_t *chip, irq_phys_t start, irq_phys_t end)
 Unregister all instances of the given IRQ chip within the specified range.
 
uint64_t irq_chip_amount (void)
 Get the number of registered IRQ chips.
 
uint64_t irq_handler_register (irq_virt_t virt, irq_func_t func, void *private)
 Register an IRQ handler for a virtual IRQ.
 
void irq_handler_unregister (irq_func_t func, irq_virt_t virt)
 Unregister an IRQ handler.
 

Macro Definition Documentation

◆ IRQ_PHYS_NONE

#define IRQ_PHYS_NONE   UINT32_MAX

Constant representing no physical IRQ.

Definition at line 51 of file irq.h.

◆ IRQ_INVOKE

#define IRQ_INVOKE (   virt)    asm volatile("int %0" : : "i"(virt));

Invoke the given virtual IRQ.

Warning
Even tho its technically possible to use the int instruction with interrupts disabled, doing so will cause a panic in the interrupt handler as a sanity check. Therefore only use this macro with interrupts enabled.
Parameters
virtThe virtual IRQ to invoke.

Definition at line 290 of file irq.h.

Typedef Documentation

◆ irq_phys_t

Physical IRQ numbers.

Definition at line 46 of file irq.h.

◆ irq_virt_t

Virtual IRQ numbers.

Definition at line 57 of file irq.h.

◆ irq_func_t

typedef void(* irq_func_t) (irq_func_data_t *data)

Callback function type for IRQs.

Definition at line 74 of file irq.h.

Enumeration Type Documentation

◆ irq_flags_t

IRQ flags.

Specifies the expected behaviour of an IRQ to a IRQ chip.

Enumerator
IRQ_POLARITY_HIGH 

If set, the IRQ is active high.

IRQ_POLARITY_LOW 

If set, the IRQ is active low. Otherwise, active high.

IRQ_TRIGGER_LEVEL 

If set, the IRQ is level triggered.

IRQ_TRIGGER_EDGE 

If set, the IRQ is edge triggered. Otherwise, level triggered.

IRQ_EXCLUSIVE 

If set, the IRQ is exclusive (not shared).

IRQ_SHARED 

If set, the IRQ is shared.

Definition at line 93 of file irq.h.

Function Documentation

◆ irq_init()

void irq_init ( void  )

Initialize the IRQ subsystem.

Definition at line 111 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_dispatch()

void irq_dispatch ( interrupt_frame_t frame,
cpu_t self 
)

Dispatch an IRQ.

This function is called from interrupt_handler() when an IRQ is received. It will call all registered handlers for the IRQ and handle acknowledging and EOI as needed.

Should not be called for exceptions.

Will panic on failure.

Parameters
frameThe interrupt frame of the IRQ.
selfThe CPU on which the IRQ was received.

Definition at line 127 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_virt_alloc()

uint64_t irq_virt_alloc ( irq_virt_t out,
irq_phys_t  phys,
irq_flags_t  flags,
cpu_t cpu 
)

Allocate a virtual IRQ mapped to the given physical IRQ.

Will return an existing virtual IRQ if the physical IRQ is already allocated with the same flags and is shared. In this case its reference count will be incremented.

Will succeed even if no IRQ chip is registered for the given physical IRQ, in such a case, the IRQ will be enabled only when a appropriate IRQ chip is registered.

Note
The IRQ will only be enabled if there are registered handlers for it, otherwise it will remain disabled until a handler is registered.
Todo:
CPU load balancing?
Parameters
outPointer to store the allocated virtual IRQ.
physThe physical IRQ number.
flagsThe IRQ flags.
cpuThe target CPU for the IRQ, or NULL for the current CPU.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EBUSY: The IRQ is already allocated with incompatible flags, or is exclusive.
  • ENOSPC: No more virtual IRQs can be allocated.
  • Other errors as returned by the IRQ chip's enable function.

Definition at line 171 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_virt_free()

void irq_virt_free ( irq_virt_t  virt)

Free a previously allocated virtual IRQ.

The IRQ will be disabled and its handlers freed only when no more references to it exists.

Parameters
virtThe virtual IRQ to free.

Definition at line 253 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_virt_set_affinity()

uint64_t irq_virt_set_affinity ( irq_virt_t  virt,
cpu_t cpu 
)

Change the CPU responsible for an IRQ.

Parameters
virtThe virtual IRQ to set the affinity for.
cpuThe target CPU for the IRQ.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • ENOENT: The given virtual IRQ is not a external vector.
  • ENODEV: The IRQ has no associated IRQ chip.
  • Other errors as returned by the IRQ chip's enable functions.

Definition at line 291 of file irq.c.

Here is the call graph for this function:

◆ irq_chip_register()

uint64_t irq_chip_register ( irq_chip_t chip,
irq_phys_t  start,
irq_phys_t  end,
void *  private 
)

Register an IRQ chip for a range of physical IRQs.

The same chip can be registered multiple times for ranges that do not overlap.

Parameters
chipThe IRQ chip to register.
startThe start of the physical IRQ range.
endThe end of the physical IRQ range.
privatePrivate data for the IRQ chip, will be found in irq_t->domain->private.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • EEXIST: A chip with a domain overlapping the given range is already registered.
  • ENOMEM: Memory allocation failed.
  • Other errors as returned by the IRQ chip's enable function.

Definition at line 330 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_chip_unregister()

void irq_chip_unregister ( irq_chip_t chip,
irq_phys_t  start,
irq_phys_t  end 
)

Unregister all instances of the given IRQ chip within the specified range.

Will NOT free any IRQs or handlers associated with the chip(s), but it will disable them. If another chip is registered in the same range, the IRQs will be remapped to that chip.

Parameters
chipThe IRQ chip to unregister, or NULL for no-op.
startThe start of the physical IRQ range.
endThe end of the physical IRQ range.

Definition at line 374 of file irq.c.

Here is the call graph for this function:

◆ irq_chip_amount()

uint64_t irq_chip_amount ( void  )

Get the number of registered IRQ chips.

Returns
The number of registered IRQ chips.

Definition at line 419 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_handler_register()

uint64_t irq_handler_register ( irq_virt_t  virt,
irq_func_t  func,
void *  private 
)

Register an IRQ handler for a virtual IRQ.

If this is the first handler for the IRQ, the IRQ will be enabled.

Parameters
virtThe virtual IRQ to register the handler for.
funcThe handler function to register.
privateThe private data to pass to the handler function.
Returns
On success, 0. On failure, ERR and errno is set to:
  • EINVAL: Invalid parameters.
  • ENOENT: The given virtual IRQ is not a external vector.
  • EEXIST: The given handler is already registered for the given virtual IRQ.
  • ENOMEM: Memory allocation failed.
  • Other errors as returned by the IRQ chip's enable function.

Definition at line 425 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ irq_handler_unregister()

void irq_handler_unregister ( irq_func_t  func,
irq_virt_t  virt 
)

Unregister an IRQ handler.

If there are no more handlers registered for the IRQ, it will be disabled.

Parameters
funcThe handler function to unregister, or NULL for no-op.
virtThe virtual IRQ to unregister the handler from.

Definition at line 474 of file irq.c.

Here is the call graph for this function:
Here is the caller graph for this function: