AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
irq.c
Go to the documentation of this file.
1
8
9#include <core/system.h>
10#include <core/string.h>
11#include <mm/mm.h>
12#include <dev/irq.h>
13#include <platform/virt.h>
14#include <aquila/errno.h>
15
16MALLOC_DEFINE(M_IRQ, "irq", "IRQ handler");
17
19struct handler {
21 void *arg;
22 struct handler *next;
23};
24
25/* Each interrupt's handlers, and how many times it came. */
26static struct handler *handlers[IRQ_NR];
28
29/*
30 * Installs a handler for an interrupt.
31 */
32int irq_install(unsigned irq, irq_handler_t fn, void *arg)
33{
34 if (irq >= IRQ_NR)
35 return -EINVAL;
36
37 struct handler *h = kmalloc(sizeof(*h), &M_IRQ, M_ZERO);
38
39 if (!h)
40 return -ENOMEM;
41
42 h->fn = fn;
43 h->arg = arg;
44
45 int first = !handlers[irq];
46 struct handler **p = &handlers[irq];
47
48 while (*p)
49 p = &(*p)->next;
50
51 *p = h;
52
53 if (first)
54 gic_enable(irq);
55
56 return 0;
57}
58
59/*
60 * Uninstalls a handler that irq_install() installed.
61 */
62void irq_uninstall(unsigned irq, irq_handler_t fn, void *arg)
63{
64 if (irq >= IRQ_NR)
65 return;
66
67 for (struct handler **p = &handlers[irq]; *p; p = &(*p)->next) {
68 struct handler *h = *p;
69
70 if (h->fn == fn && h->arg == arg) {
71 *p = h->next;
72 kfree(h);
73 break;
74 }
75 }
76
77 if (!handlers[irq])
78 gic_disable(irq);
79}
80
84void irq_handle(void)
85{
86 unsigned irq = gic_ack();
87
88 if (irq >= 1020) /* a spurious interrupt: there's none */
89 return;
90
91 if (irq < IRQ_NR) {
92 counts[irq]++;
93
94 for (struct handler *h = handlers[irq]; h; h = h->next)
95 h->fn(h->arg);
96 }
97
98 gic_eoi(irq);
99}
100
101/*
102 * Writes `/proc/interrupts`: the controller, and how many times each
103 * interrupt came.
104 */
105int arch_interrupts_info(char *buf, size_t size)
106{
107 int sz = snprintf(buf, size, "controller: gicv2\n");
108
109 for (unsigned i = 0; i < IRQ_NR && (size_t) sz < size; ++i)
110 if (counts[i])
111 sz += snprintf(buf + sz, size - sz, "%d: %ld\n", i, counts[i]);
112
113 return sz;
114}
void irq_uninstall(unsigned irq, irq_handler_t fn, void *arg)
Removes a handler that irq_install() installed.
Definition irq.c:62
static uint64_t counts[IRQ_NR]
Definition irq.c:27
int arch_interrupts_info(char *buf, size_t size)
Definition irq.c:105
int irq_install(unsigned irq, irq_handler_t fn, void *arg)
Installs a handler for an IRQ.
Definition irq.c:32
static struct handler * handlers[IRQ_NR]
Definition irq.c:26
void gic_eoi(unsigned irq)
Tells the GIC that an interrupt has been handled (end of interrupt).
Definition gic.c:95
unsigned gic_ack(void)
Acknowledges the interrupt that came.
Definition gic.c:85
void gic_disable(unsigned irq)
Disables (masks) an interrupt.
Definition gic.c:75
void gic_enable(unsigned irq)
Enables (unmasks) an interrupt.
Definition gic.c:65
void(*) irq_handler_t(void *arg)
Definition irq.h:21
#define MALLOC_DEFINE(type, _name, _desc)
Definition kvmem.h:30
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
Definition kvmem.c:123
#define M_ZERO
Definition kvmem.h:26
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
int snprintf(char *s, size_t n, const char *fmt,...)
Formats a string into a buffer.
Definition snprintf.c:226
__SIZE_TYPE__ size_t
Definition stddef.h:7
unsigned long long int uint64_t
Definition stddef.h:23
An installed handler, on its interrupt's list.
Definition irq.c:19
void * arg
Definition irq.c:21
struct handler * next
Definition irq.c:22
irq_handler_t fn
Definition irq.c:20
void irq_handle(void)
Runs the handlers of the interrupt that came, then tells the GIC it's done, before any thread switch,...
Definition irq.c:84
#define IRQ_NR
Definition virt.h:43