Voxia OS v0.0.1
Hobby Project Operating System Targeting x86-64
Loading...
Searching...
No Matches
interrupt.c
Go to the documentation of this file.
1#include "./interrupt.h"
2#include "autoconf.h"
3#include "console/console.h"
4#include "hal/apic/apic.h"
5#include "hal/cpu/paging.h"
6#include "init/init.h"
7#include <hal/cpu/core.h>
8#include <libk/debug/debug.h>
9#include <libk/io.h>
10#include <libk/serial.h>
11#include <memory/memory_utils.h>
12#include <memory/vm_manager.h>
13#include <procc/scheduler.h>
14#include <procc/task.h>
15#include <spinlock.h>
16#include <str.h>
17#include <type.h>
18
20
21static void interrupt_io_wait() { outb(0x80, 0); }
22
38
39static void interrupt_reload(interrupt_pointers_t* ptr,
40 interrupt_entry_t* tbl) {
41 ptr->limit = MAX_INTERRUPTS * sizeof(interrupt_entry_t) - 1;
42 ptr->base = (uint64_t)&tbl[0];
43 asm volatile("lidt %0" : : "m"(*ptr));
44 asm volatile("sti");
45}
46
47extern void* int_table[];
48// extern void syscall_interupt();
49
50static void interrupt_register(interrupt_entry_t* entries, int n, void* handler,
51 int selector, uint8_t ist, uint8_t type_attr) {
52 entries[n].offset_low = (uint16_t)((uint64_t)handler & 0xFFFF);
53 entries[n].selector = (uint16_t)selector;
54 entries[n].ist = ist;
55 entries[n].type_attr = type_attr;
56 entries[n].offset_mid = (uint16_t)((uint64_t)handler >> 16);
57 entries[n].offset_high = (uint64_t)handler >> 32;
58 entries[n].zero = 0;
59
60 // serial_printf("registered interrupt 0x%x\n", n);
61 // serial_printf("low %x\n", entries[n].offset_low);
62 // serial_printf("mid %x\n", entries[n].offset_mid);
63 // serial_printf("high %x\n", entries[n].offset_high);
64 // serial_printf("selector %x\n", entries[n].selector);
65 // serial_printf("ist %x\n", entries[n].ist);
66 // serial_printf("type_attr %x\n", entries[n].type_attr);
67 // serial_printf("handler 0x%x", handler);
68}
69
70void irq_register(uint8_t core, int n, void* handler, boolean_t use_default_isr,
71 uint16_t selector, uint8_t ist, uint8_t type_attr) {
72
73 irq_entry_t* entry = &interrupt_per_core_data[core].irq_entries[n];
74 int slot = -1;
75
76 for (;;) {
77 uint8_t old = __atomic_load_n(&entry->mask, __ATOMIC_ACQUIRE);
78 if (old == 0xFF)
79 return;
80
81 uint8_t free_mask = (uint8_t)~old;
82 int e = __builtin_ctz(free_mask);
83 uint8_t new = (uint8_t)(old | (1 << e));
84
85 if (__atomic_compare_exchange_n(&entry->mask, &old, new, false,
86 __ATOMIC_ACQ_REL,
87 __ATOMIC_RELAXED)) {
88 slot = e;
89 break;
90 }
91 }
92
93 entry->handler[slot] = handler;
94 __atomic_store_n(&entry->use_default_isr, use_default_isr,
95 __ATOMIC_RELAXED);
96 __atomic_store_n(&entry->configured, true, __ATOMIC_RELEASE);
97
98 if (use_default_isr) {
100 interrupt_per_core_data[core].interrupt_entries, n,
101 (void*)(uint64_t)int_table[n], selector, ist, type_attr);
102 } else {
104 interrupt_per_core_data[core].interrupt_entries, n, handler,
105 selector, ist, type_attr);
106 }
107}
108
110 for (uint16_t i = 0x50; i < MAX_INTERRUPTS; i++) {
111 irq_entry_t* entry =
112 &interrupt_per_core_data[core].irq_entries[i];
113
114 /* Coba klaim slot: configured harus masih false */
115 boolean_t expected = false;
116 if (__atomic_compare_exchange_n(&entry->allocated, &expected,
117 true, false, __ATOMIC_ACQ_REL,
118 __ATOMIC_RELAXED)) {
119 return i;
120 }
121 }
122 return 0xFFFF;
123}
124
128 for (int i = 0; i < MAX_INTERRUPTS; i++)
130 interrupt_per_core_data[core].interrupt_entries, i,
131 (void*)(uint64_t)int_table[i], 0x28, 0,
133
134 if (core == 0)
136
137 interrupt_reload(&interrupt_per_core_data[core].interrupt_pointers,
138 interrupt_per_core_data[core].interrupt_entries);
139
140 // interrupt_register(interrupt_per_core_data[core].interrupt_entries,
141 // 0x73, (void*) (uint64_t) syscall_interupt, 0x28, 0,
142 // INTERRUPT_ATTR_USER);
143}
144
145INIT(Interrupt) {
147 irq_setup(0);
148}
149
150static const char* exception_messages[] = {
151 "Division By Zero",
152 "Debug",
153 "Non Maskable Interrupt",
154 "Breakpoint",
155 "Into Detected Overflow",
156 "Out of Bounds",
157 "Invalid Opcode",
158 "No Coprocessor",
159 "Double Fault",
160 "Coprocessor Segment Overrun",
161 "Bad TSS",
162 "Segment Not Present",
163 "Stack Fault",
164 "General Protection Fault",
165 "Page Fault",
166 "reserved",
167 "x87 FPU Floating Point Error",
168 "Alignment Check",
169 "Machine Check",
170 "SIMD Floating Point Exception",
171 "reserved",
172 "reserved",
173 "reserved",
174 "reserved",
175 "reserved",
176 "reserved",
177 "reserved",
178 "reserved",
179 "reserved",
180 "reserved",
181 "reserved",
182 "reserved",
183};
184
211
214extern void init_runtime();
216extern void timer_handle(void);
217extern void virtio_irq();
220
222
223__attribute__((no_stack_protector)) extern void
224vxInterruptHandler(interrupt_stack_frame_t* rsp, fpu_state_t* fpu) {
225 UNUSED(fpu);
226 auto cpu = get_current_core_data();
227 auto cpu_id = cpu->core_id;
228
229 uint64_t int_number = rsp->int_no;
230
231 if (int_number < 32) {
232 uintptr_t cr2 = 0;
233
234 if (int_number == PAGE_FAULT) {
235 asm volatile("mov %%cr2, %0" : "=r"(cr2));
236 // KDEBUG(DEBUG_LEVEL_ERROR, "page fault 0x%x\n", cr2);
237 serial2_printf("page fault 0x%x\n", cr2);
238 auto err = rsp->err_code;
240 " err bits: present=%d write=%d user=%d nx=%d\n",
241 err & 1, (err >> 1) & 1, (err >> 2) & 1,
242 (err >> 4) & 1);
243 }
244
245 serial2_printf("\n\n[EXCEPTION] %s (vector %d)\n",
246 exception_messages[int_number], int_number);
247 serial2_printf(" rip=0x%x rsp=0x%x err=0x%x cr2=0x%x\n",
248 rsp->rip, rsp->rsp, rsp->err_code, cr2);
249 serial2_printf(" rax=0x%x rbp=0x%x rcx=0x%x rdx=0x%x\n",
250 rsp->rax, rsp->rbp, rsp->rcx, rsp->rdx);
251
252 // console_printf("\n\n[EXCEPTION] %s (vector %d)\n",
253 // exception_messages[int_number], int_number);
254 // console_printf(" rip=0x%x rsp=0x%x err=0x%x cr2=0x%x\n",
255 // rsp->rip, rsp->rsp, rsp->err_code, cr2);
256 // console_printf(" rax=0x%x rbp=0x%x rcx=0x%x rdx=0x%x\n",
257 // rsp->rax, rsp->rbp, rsp->rcx, rsp->rdx);
258
259 const scheduler_queue_t* queue =
261 if (queue && queue->thread) {
262 LOG2_ERROR("INTERRUPT",
263 "Exception %s on thread id %d at rip=0x%x "
264 "cr2=0x%x",
265 exception_messages[int_number],
266 queue->thread->id, rsp->rip, cr2);
267 queue->thread->state = THREAD_STATE_TERMINATED;
269 // INFLOOP;
270 } else {
271
272 INFLOOP;
273
274 /* Tidak ada thread — terjadi di konteks kernel awal,
275 * tidak bisa di-recover, halt. */
276 }
277
278 goto end;
279 }
280
281 // paging_reload(paging_get_highest_page_map());
282
283 {
284
285 irq_entry_t* irq =
286 &interrupt_per_core_data[cpu_id].irq_entries[int_number];
287
288 if (__atomic_load_n(&irq->configured, __ATOMIC_ACQUIRE)) {
289 if (irq->use_default_isr) {
290 uint8_t m = __atomic_load_n(&irq->mask,
291 __ATOMIC_ACQUIRE);
292 while (m) {
293 int i = __builtin_ctz(m);
294 void* h = __atomic_load_n(
295 &irq->handler[i], __ATOMIC_ACQUIRE);
296 if (h)
297 ((void (*)(
299 h)(rsp);
300 m &= (m - 1);
301 }
302 }
303 }
304 }
305
306end:
307 apic_eoi();
308}
struct SDT h
Definition acpi.h:0
void apic_eoi()
Definition apic.c:102
each_core_data * get_current_core_data(void)
Definition core.c:54
void update_core_gs(uint8_t id)
Definition core.c:39
volatile uint64_t addr
Definition e1000.hpp:0
uint64_t ist[7]
Definition gdt.h:3
uint64_t rsp[3]
Definition gdt.h:1
@ THREAD_STATE_TERMINATED
Definition thread.h:26
typedef __attribute__
Definition msi.c:47
#define INFLOOP
Definition init.h:32
#define INIT(fn)
Definition init.h:26
uintptr_t rip_before_run_elf
Definition elf.c:15
EXCEPTION_ID
Definition interrupt.c:185
@ DEBUG
Definition interrupt.c:187
@ VMM_COMMUNICATION_EXCEPTION
Definition interrupt.c:208
@ SEGMENT_NOT_PRESENT
Definition interrupt.c:197
@ COPROCESSOR_SEGMENT_OVERRUN
Definition interrupt.c:195
@ BAD_TSS
Definition interrupt.c:196
@ NO_COPROCESSOR
Definition interrupt.c:193
@ VIRTUALIZATION_EXCEPTION
Definition interrupt.c:205
@ PAGE_FAULT
Definition interrupt.c:200
@ INTO_DETECTED_OVERFLOW
Definition interrupt.c:190
@ CONTORL_PROTECTION_EXCEPTION
Definition interrupt.c:206
@ DIVIDE_BY_ZERO
Definition interrupt.c:186
@ BREAKPOINT
Definition interrupt.c:189
@ MACHINE_CHECK
Definition interrupt.c:203
@ ALIGNMENT_CHECK
Definition interrupt.c:202
@ NON_MASKABLE_INTERRUPT
Definition interrupt.c:188
@ INVALID_OPCODE
Definition interrupt.c:192
@ SECURITY_EXCEPTION
Definition interrupt.c:209
@ STACK_FAULT
Definition interrupt.c:198
@ OUT_OF_BOUNDS
Definition interrupt.c:191
@ X87_FPU_FLOATING_POINT_ERROR
Definition interrupt.c:201
@ HYPERVISOR_INJECTION_EXCEPTION
Definition interrupt.c:207
@ DOUBLE_FAULT
Definition interrupt.c:194
@ GENERAL_PROTECTION_FAULT
Definition interrupt.c:199
@ SIMD_FLOATING_POINT_EXCEPTION
Definition interrupt.c:204
void jump_usermode(uintptr_t addr)
static interrupt_per_core_data_t interrupt_per_core_data[VOXIA_MAX_CORE]
Definition interrupt.c:19
static void interrupt_register(interrupt_entry_t *entries, int n, void *handler, int selector, uint8_t ist, uint8_t type_attr)
Definition interrupt.c:50
void timer_handle(void)
boolean_t g__scheduler__is__running
Definition scheduler.c:19
void init_runtime()
spinlock_t int_lock
Definition interrupt.c:221
boolean_t elf_has_running
Definition elf.c:14
static const char * exception_messages[]
Definition interrupt.c:150
static void interrupt_reload(interrupt_pointers_t *ptr, interrupt_entry_t *tbl)
Definition interrupt.c:39
uint16_t irq_alloc_entry(uint8_t core)
Definition interrupt.c:109
void * int_table[]
static void interrupt_io_wait()
Definition interrupt.c:21
void irq_register(uint8_t core, int n, void *handler, boolean_t use_default_isr, uint16_t selector, uint8_t ist, uint8_t type_attr)
Definition interrupt.c:70
static void interrupt_pic_remap(void)
Definition interrupt.c:23
boolean_t is_running_program
Definition interrupt.c:212
void irq_setup(uint16_t core)
Definition interrupt.c:125
void virtio_irq()
fpu_state_t * fpu
Definition interrupt.h:84
#define PIC2_COMMAND
Definition interrupt.h:9
#define ICW1_INIT
Definition interrupt.h:16
#define ICW4_8086
Definition interrupt.h:18
#define INTERRUPT_ATTR_KERNEL
Definition interrupt.h:28
#define ICW1_ICW4
Definition interrupt.h:12
#define MAX_INTERRUPTS
Definition interrupt.h:24
#define PIC2_DATA
Definition interrupt.h:10
#define PIC1_COMMAND
Definition interrupt.h:7
#define PIC1_DATA
Definition interrupt.h:8
static void outb(uint16_t port, uint8_t value)
Definition io.h:6
void serial2_printf(const char *fmt,...)
void sch_restore_to_next_thread(volatile interrupt_stack_frame_t *rsp, uint16_t core_id)
Definition scheduler.c:305
scheduler_queue_t * vxSchedulerGetCurrentQueue(uint16_t core)
Definition scheduler.c:29
struct scheduler_queue scheduler_queue_t
Definition scheduler.h:9
#define LOG2_ERROR(mod, fmt,...)
Definition serial.h:38
void memset(void *ptr, int value, size_t num)
Definition interrupt.h:63
void * handler[16]
Definition interrupt.h:68
boolean_t allocated
Definition interrupt.h:67
uint8_t mask
Definition interrupt.h:64
boolean_t use_default_isr
Definition interrupt.h:65
boolean_t configured
Definition interrupt.h:66
unsigned short uint16_t
Definition type.h:13
uint8_t boolean_t
Definition type.h:89
unsigned long uintptr_t
Definition type.h:73
#define UNUSED(x)
Definition type.h:100
unsigned long uint64_t
Definition type.h:25
unsigned char uint8_t
Definition type.h:7
int core
Definition vm_manager.h:5
workqueue_t * queue
Definition voxmo.h:9
struct xhci_slot_ctx slot
Definition xhci.hpp:0
uint64_t ptr
Definition xhci.hpp:0