| 1 | /* @title: IRQs */ |
| 2 | #pragma once |
| 3 | #include <smp/core.h> |
| 4 | #include <stdbool.h> |
| 5 | #include <stdint.h> |
| 6 | #include <structures/list.h> |
| 7 | #include <types/types.h> |
| 8 | |
| 9 | #define IRQ_DIV_BY_Z 0x0 |
| 10 | #define IRQ_DEBUG 0x1 |
| 11 | #define IRQ_NMI 0x2 |
| 12 | #define IRQ_BREAKPOINT 0x3 |
| 13 | #define IRQ_DBF 0x8 |
| 14 | #define IRQ_SSF 0xC |
| 15 | #define IRQ_GPF 0xD |
| 16 | #define IRQ_PAGE_FAULT 0xE |
| 17 | #define IRQ_TIMER 0x20 |
| 18 | #define IRQ_SCHEDULER IRQ_TIMER |
| 19 | #define IRQ_TLB_SHOOTDOWN 0x22 |
| 20 | #define IRQ_NOP 0x24 |
| 21 | #define IRQ_EXCEPTION_COUNT 32 |
| 22 | |
| 23 | struct irq_context; |
| 24 | struct irq_desc; |
| 25 | |
| 26 | enum irq_result { |
| 27 | IRQ_NONE = 0, |
| 28 | IRQ_HANDLED = 1, |
| 29 | }; |
| 30 | |
| 31 | typedef enum irq_result (*irq_handler_t)(void *ctx, uint8_t vector, |
| 32 | struct irq_context *ictx); |
| 33 | |
| 34 | enum irq_flags { |
| 35 | IRQ_FLAG_SHARED = 1, /* IRQ is shared between things */ |
| 36 | IRQ_FLAG_LEVEL_TRIGGERED = 1 << 1, |
| 37 | IRQ_FLAG_EDGE_TRIGGERED = 1 << 2, |
| 38 | IRQ_FLAG_NONE = 0, |
| 39 | }; |
| 40 | |
| 41 | struct irq_action { |
| 42 | irq_handler_t handler; |
| 43 | void *data; |
| 44 | struct list_head list; |
| 45 | }; |
| 46 | |
| 47 | struct irq_chip { |
| 48 | const char *name; |
| 49 | |
| 50 | void (*mask)(struct irq_desc *); |
| 51 | void (*unmask)(struct irq_desc *); |
| 52 | void (*eoi)(struct irq_desc *); |
| 53 | |
| 54 | void (*set_affinity)(struct irq_desc *, struct cpu_mask *); |
| 55 | int (*set_rate_limit)(struct irq_desc *, time_t interval); |
| 56 | }; |
| 57 | |
| 58 | struct irq_desc { |
| 59 | uint8_t vector; |
| 60 | enum irq_flags flags; |
| 61 | |
| 62 | const char *name; |
| 63 | |
| 64 | struct irq_chip *chip; |
| 65 | void *chip_data; |
| 66 | |
| 67 | struct list_head actions; |
| 68 | |
| 69 | struct cpu_mask affinity; |
| 70 | struct cpu_mask masked_cpus; |
| 71 | |
| 72 | bool present; /* Have we set handlers? */ |
| 73 | bool allocated; /* Has this been allocated? */ |
| 74 | bool enabled; |
| 75 | }; |
| 76 | |
| 77 | struct irq_context { |
| 78 | uint64_t rax; |
| 79 | uint64_t rbx; |
| 80 | uint64_t rcx; |
| 81 | uint64_t rdx; |
| 82 | uint64_t rbp; |
| 83 | uint64_t rdi; |
| 84 | uint64_t rsi; |
| 85 | uint64_t r8; |
| 86 | uint64_t r9; |
| 87 | uint64_t r10; |
| 88 | uint64_t r11; |
| 89 | uint64_t r12; |
| 90 | uint64_t r13; |
| 91 | uint64_t r14; |
| 92 | uint64_t r15; |
| 93 | uint64_t error_code; |
| 94 | uint64_t rip; |
| 95 | uint64_t cs; |
| 96 | uint64_t rflags; |
| 97 | uint64_t rsp; |
| 98 | uint64_t ss; |
| 99 | }; |
| 100 | |
| 101 | void irq_register(char *name, uint8_t vector, irq_handler_t handler, void *ctx, |
| 102 | enum irq_flags flags); |
| 103 | void irq_register_full(struct irq_desc *d); |
| 104 | void irq_set_chip(uint8_t vector, struct irq_chip *chip, void *data); |
| 105 | |
| 106 | static inline void irq_mark_self_in_interrupt(bool new) { |
| 107 | smp_core()->in_interrupt = new; |
| 108 | } |
| 109 | |
| 110 | static inline bool irq_in_interrupt(void) { |
| 111 | return smp_core()->in_interrupt; |
| 112 | } |
| 113 | |
| 114 | static inline bool irq_in_thread_context(void) { |
| 115 | return !irq_in_interrupt(); |
| 116 | } |
| 117 | |
| 118 | static inline bool irq_vector_is_exception(uint8_t vector) { |
| 119 | return vector < IRQ_EXCEPTION_COUNT; |
| 120 | } |
| 121 | |
| 122 | void ipi_send(uint32_t apic_id, uint8_t vector); |
| 123 | void nmi_send(uint32_t apic_id); |
| 124 | |
| 125 | void irq_set_alloc(int32_t entry, bool used); |
| 126 | int32_t irq_alloc_entry(void); |
| 127 | void irq_free_entry(int32_t entry); |
| 128 | bool irq_is_installed(int32_t entry); |
| 129 | void irq_free_entry(int32_t entry); |
| 130 | void irq_disable(irq_t irq); |
| 131 | void irq_enable(irq_t irq); |
| 132 | |