summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/idt.c
blob: 05dcf438ebd19e1d88b0091e5742d3a991545d20 (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
70
71
72
73
74
75
76
77
#include "tables.h"
#include "cpu.h"
#include "lib/jove.h"
#include "io/log.h"

PAGEALIGN
static struct InterruptTrapGate s_idtd[48];
static struct Registers *(*s_int_handlers[48])(struct Registers*);
static struct XDTR s_idtr = {
    .length = sizeof(s_idtd) - 1,
    .address = (uintptr_t)&s_idtd
};

uint64_t __isr_err;
uint64_t __isr_num;

void
int_set_handler(uint8_t code, struct Registers *(*handler)(struct Registers*))
{
    if(code >= 48) return;
    s_int_handlers[code] = handler;
}

struct Registers*
irq_handle(struct Registers *state)
{
    if(__isr_num < 48) {
        if(s_int_handlers[__isr_num] != NULL) {
            return s_int_handlers[__isr_num](state);
        }
    }
    klogf("Interrupt %i\nerror code %#016X\n", __isr_num, __isr_err);
    klogf("IP:  %#016X\n", state->ip);
    klogf("AX:  %#016X\n", state->ax);
    klogf("BX:  %#016X\n", state->bx);
    klogf("CX:  %#016X\n", state->cx);
    klogf("DX:  %#016X\n", state->dx);
    klogf("SI:  %#016X\n", state->si);
    klogf("DI:  %#016X\n", state->di);
    klogf("BP:  %#016X\n", state->bp);
    klogf("R8:  %#016X\n", state->r8);
    klogf("R9:  %#016X\n", state->r9);
    klogf("R10: %#016X\n", state->r10);
    klogf("R11: %#016X\n", state->r11);
    klogf("R12: %#016X\n", state->r12);
    klogf("R13: %#016X\n", state->r13);
    klogf("R14: %#016X\n", state->r14);
    klogf("R15: %#016X\n", state->r15);
    kpanic("Unhandled exception\n");
    return state;
}

extern void x86_64_lidt(struct XDTR *idtr);
void
x86_64_load_idt(void)
{
    extern uintptr_t __isr_stubs[22];
    for(int i = 0; i < 22; i++)
    {
        uintptr_t base = __isr_stubs[i];
        s_idtd[i] = (struct InterruptTrapGate){
            .base_0_15 = (base & 0xFFFF),
            .segment_selector = 0x8,
            .ist = 0,
            .zero_0 = 0,
            .type = 0xE,
            .zero_1 = 0,
            .dpl = 0,
            .p = 1,
            .base_16_31 = (base >> 16) & 0xFFFF,
            .base_32_63 = (base >> 32) & 0xFFFFFFFF,
            .resv = 0
        };
        klogf("INT %2i : %#016X (%016X)\n", i, base, s_idtd[i]);
    }
    x86_64_lidt(&s_idtr);
}