fix: passing intr_ctx to soft_iret corrupts the stack of next proccess when performin...
[lunaix-os.git] / lunaix-os / kernel / asm / x86 / interrupts.c
1 #include <arch/x86/interrupts.h>
2 #include <hal/apic.h>
3 #include <hal/cpu.h>
4 #include <lunaix/mm/page.h>
5 #include <lunaix/mm/vmm.h>
6 #include <lunaix/process.h>
7 #include <lunaix/sched.h>
8 #include <lunaix/syslog.h>
9 #include <lunaix/tty/tty.h>
10
11 LOG_MODULE("intr")
12
13 static int_subscriber subscribers[256];
14
15 static int_subscriber fallback = (int_subscriber)0;
16
17 void
18 intr_subscribe(const uint8_t vector, int_subscriber subscriber)
19 {
20     subscribers[vector] = subscriber;
21 }
22
23 void
24 intr_unsubscribe(const uint8_t vector, int_subscriber subscriber)
25 {
26     if (subscribers[vector] == subscriber) {
27         subscribers[vector] = (int_subscriber)0;
28     }
29 }
30
31 void
32 intr_set_fallback_handler(int_subscriber subscribers)
33 {
34     fallback = subscribers;
35 }
36
37 extern x86_page_table* __kernel_ptd;
38
39 void
40 intr_handler(isr_param* param)
41 {
42     __current->intr_ctx = *param;
43
44 #ifdef USE_KERNEL_PT
45     cpu_lcr3(__kernel_ptd);
46
47     vmm_mount_pd(PD_MOUNT_1, __current->page_table);
48 #endif
49
50     isr_param* lparam = &__current->intr_ctx;
51
52     if (lparam->vector <= 255) {
53         int_subscriber subscriber = subscribers[lparam->vector];
54         if (subscriber) {
55             subscriber(param);
56             goto done;
57         }
58     }
59
60     if (fallback) {
61         fallback(lparam);
62         goto done;
63     }
64
65     kprint_panic("INT %u: (%x) [%p: %p] Unknown",
66                  lparam->vector,
67                  lparam->err_code,
68                  lparam->cs,
69                  lparam->eip);
70
71 done:
72     // for all external interrupts except the spurious interrupt
73     //  this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5
74     if (lparam->vector >= EX_INTERRUPT_BEGIN &&
75         lparam->vector != APIC_SPIV_IV) {
76         apic_done_servicing();
77     }
78
79 #ifdef USE_KERNEL_PT
80     cpu_lcr3(__current->page_table);
81 #endif
82     return;
83 }