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
23struct irq_context;
24struct irq_desc;
25
26enum irq_result {
27 IRQ_NONE = 0,
28 IRQ_HANDLED = 1,
29};
30
31typedef enum irq_result (*irq_handler_t)(void *ctx, uint8_t vector,
32 struct irq_context *ictx);
33
34enum 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
41struct irq_action {
42 irq_handler_t handler;
43 void *data;
44 struct list_head list;
45};
46
47struct 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
58struct 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
77struct 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
101void irq_register(char *name, uint8_t vector, irq_handler_t handler, void *ctx,
102 enum irq_flags flags);
103void irq_register_full(struct irq_desc *d);
104void irq_set_chip(uint8_t vector, struct irq_chip *chip, void *data);
105
106static inline void irq_mark_self_in_interrupt(bool new) {
107 smp_core()->in_interrupt = new;
108}
109
110static inline bool irq_in_interrupt(void) {
111 return smp_core()->in_interrupt;
112}
113
114static inline bool irq_in_thread_context(void) {
115 return !irq_in_interrupt();
116}
117
118static inline bool irq_vector_is_exception(uint8_t vector) {
119 return vector < IRQ_EXCEPTION_COUNT;
120}
121
122void ipi_send(uint32_t apic_id, uint8_t vector);
123void nmi_send(uint32_t apic_id);
124
125void irq_set_alloc(int32_t entry, bool used);
126int32_t irq_alloc_entry(void);
127void irq_free_entry(int32_t entry);
128bool irq_is_installed(int32_t entry);
129void irq_free_entry(int32_t entry);
130void irq_disable(irq_t irq);
131void irq_enable(irq_t irq);
132