|
PatchworkOS
c9fea19
A non-POSIX operating system.
|
Interrupt Requests (IRQs) More...
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.
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.
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. | |
| #define IRQ_PHYS_NONE UINT32_MAX |
| #define IRQ_INVOKE | ( | virt | ) | asm volatile("int %0" : : "i"(virt)); |
Invoke the given virtual IRQ.
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.| virt | The virtual IRQ to invoke. |
| typedef void(* irq_func_t) (irq_func_data_t *data) |
| enum irq_flags_t |
IRQ flags.
Specifies the expected behaviour of an IRQ to a IRQ chip.
| void irq_init | ( | void | ) |
| 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.
| frame | The interrupt frame of the IRQ. |
| self | The CPU on which the IRQ was received. |
Definition at line 127 of file irq.c.
| 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.
| out | Pointer to store the allocated virtual IRQ. |
| phys | The physical IRQ number. |
| flags | The IRQ flags. |
| cpu | The target CPU for the IRQ, or NULL for the current CPU. |
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.enable function. Definition at line 171 of file irq.c.
| void irq_virt_free | ( | irq_virt_t | virt | ) |
| uint64_t irq_virt_set_affinity | ( | irq_virt_t | virt, |
| cpu_t * | cpu | ||
| ) |
Change the CPU responsible for an IRQ.
| virt | The virtual IRQ to set the affinity for. |
| cpu | The target CPU for the IRQ. |
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.enable functions. Definition at line 291 of file irq.c.
| 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.
| chip | The IRQ chip to register. |
| start | The start of the physical IRQ range. |
| end | The end of the physical IRQ range. |
| private | Private data for the IRQ chip, will be found in irq_t->domain->private. |
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.enable function. Definition at line 330 of file irq.c.
| 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.
| chip | The IRQ chip to unregister, or NULL for no-op. |
| start | The start of the physical IRQ range. |
| end | The end of the physical IRQ range. |
Definition at line 374 of file irq.c.
| uint64_t irq_chip_amount | ( | void | ) |
| 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.
| virt | The virtual IRQ to register the handler for. |
| func | The handler function to register. |
| private | The private data to pass to the handler function. |
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.enable function. Definition at line 425 of file irq.c.
| 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.
| func | The handler function to unregister, or NULL for no-op. |
| virt | The virtual IRQ to unregister the handler from. |
Definition at line 474 of file irq.c.