summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/hal/idt.c
blob: 7b8bd525cc148aeba269bd6c5af27ddc6b6b5c41 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "idt.h"
#include "smp.h"
#include "gdt.h"
#include "jove.h"
#include "lib/printf.h"
#include "lib/string.h"
#include "panic/panic.h"

ALIGN(8)
static struct idt_entry s_idt[IDT_ENTRIES];

typedef void (*isr_t)(void);
extern isr_t __isrs[IDT_ENTRIES];

typedef struct int_stackframe *(*int_handler_t)(struct int_stackframe*);
int_handler_t __int_kernel_handles[IDT_ENTRIES];

struct int_user_handle __int_user_handles[IDT_ENTRIES];

static struct int_stackframe*
s_int_handle_stub(struct int_stackframe* frame)
{
    kpanic_istate(frame, "Unhandled interrupt %i at %p\n", frame->int_num, frame->int_rip);
}

struct int_stackframe*
__int_handle_body(struct int_stackframe *frame)
{
    frame = __int_kernel_handles[frame->int_num](frame);
    
    struct int_user_handle *usr_handle = &__int_user_handles[frame->int_num];
    if(usr_handle->pid == 0) return frame;

    kprintf("TODO: Handle user interrupt switching\n");
    return frame;
}

void
idt_init(void)
{
    memset(__int_user_handles, 0, sizeof(struct int_user_handle) * IDT_ENTRIES);
    for(size_t i = 0; i < IDT_ENTRIES; i++) {
        uintptr_t isr = (uintptr_t)(__isrs[i]);

        s_idt[i] = (struct idt_entry) {
            .offset_0_15 = (uint16_t)(isr & 0xFFFF),
            .segment_selector = GDT_KERNEL_CODE * 8,
            .ist = 0,
            .type = IDT_INTERRUPT_GATE,
            .dpl = 0,
            .p = 1,
            .offset_16_31 = (uint16_t)((isr >> 16) & 0xFFFF),
            .offset_32_63 = (uint32_t)(isr >> 32)
        };

        __int_kernel_handles[i] = s_int_handle_stub;
    }
}

void
idt_setup(processor_t *processor)
{
    struct idt_descriptor idtr = (struct idt_descriptor) {
        .limit = sizeof(struct idt_entry) * IDT_ENTRIES - 1,
        .base = (uint64_t)&s_idt
    };

    __asm__ volatile("lidt %0":: "m"(idtr));
}