232 lines
5.2 KiB
C
232 lines
5.2 KiB
C
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "intr.h"
|
|
#include "io.h"
|
|
#include "gdt.h"
|
|
#include "hal/hal.h"
|
|
#include "kprintf.h"
|
|
#include "compiler/attr.h"
|
|
#include "pic.h"
|
|
#include "pit.h"
|
|
#include "proc/proc.h"
|
|
#include "syscall/syscall.h"
|
|
#include "errors.h"
|
|
#include "drivers/ps2kb/ps2kb.h"
|
|
#include "ipc/pipe/pipe.h"
|
|
#include "proc/ps2kbproc/ps2kbproc.h"
|
|
#include "rbuf/rbuf.h"
|
|
|
|
typedef struct BackTraceFrame {
|
|
struct BackTraceFrame *rbp;
|
|
uint64_t rip;
|
|
} BackTraceFrame;
|
|
|
|
void backtrace(BackTraceFrame *bt) {
|
|
kprintf("Backtrace:\n");
|
|
for (size_t frame = 0; bt; frame++) {
|
|
kprintf(" 0x%llx\n", bt->rip);
|
|
bt = bt->rbp;
|
|
}
|
|
}
|
|
|
|
void hal_intr_disable(void) {
|
|
asm volatile("cli");
|
|
}
|
|
|
|
void hal_intr_enable(void) {
|
|
asm volatile("sti");
|
|
}
|
|
|
|
typedef struct {
|
|
uint16_t intrlow;
|
|
uint16_t kernelcs;
|
|
uint8_t ist;
|
|
uint8_t attrs;
|
|
uint16_t intrmid;
|
|
uint32_t intrhigh;
|
|
uint32_t resv;
|
|
} PACKED IdtGate;
|
|
|
|
typedef struct {
|
|
uint16_t limit;
|
|
uint64_t base;
|
|
} PACKED Idt;
|
|
|
|
#define ENTRIES 256
|
|
ALIGNED(0x10) static IdtGate idtgates[ENTRIES] = {0};
|
|
static Idt idt = {0};
|
|
|
|
void idt_setentry(int i, uint64_t handler, uint8_t flags) {
|
|
idtgates[i].intrlow = handler & 0xffff;
|
|
idtgates[i].kernelcs = KCODE;
|
|
idtgates[i].ist = 0;
|
|
idtgates[i].attrs = flags;
|
|
idtgates[i].intrmid = (handler >> 16) & 0xFFFF;
|
|
idtgates[i].intrhigh = (handler >> 32) & 0xFFFFFFFF;
|
|
idtgates[i].resv = 0;
|
|
}
|
|
|
|
void idt_init(void) {
|
|
idt.base = (uint64_t)&idtgates;
|
|
idt.limit = ENTRIES * sizeof(IdtGate) - 1;
|
|
asm volatile("lidt %0" :: "m"(idt) : "memory");
|
|
|
|
LOG("hal", "idt init\n");
|
|
}
|
|
|
|
extern void *ISR_REDIRTABLE[];
|
|
|
|
static const char *exceptions[] = {
|
|
"#DE", "#DB", "NMI",
|
|
"#BP", "#OF", "#BR",
|
|
"#UD", "#NM", "#DF",
|
|
"CSO", "#TS", "#NP",
|
|
"#SS", "#GP", "#PF",
|
|
"RES", "#MF", "#AC",
|
|
"#MC", "#XM", "#VE",
|
|
"#CP",
|
|
};
|
|
|
|
void intr_init(void) {
|
|
#define MKINTR(N) \
|
|
extern void intr_vec##N(void); \
|
|
idt_setentry(N, (uint64_t)&intr_vec##N, 0x8E);
|
|
|
|
MKINTR(0);
|
|
MKINTR(1);
|
|
MKINTR(2);
|
|
MKINTR(4);
|
|
MKINTR(5);
|
|
MKINTR(6);
|
|
MKINTR(7);
|
|
MKINTR(8);
|
|
MKINTR(9);
|
|
MKINTR(10);
|
|
MKINTR(11);
|
|
MKINTR(12);
|
|
MKINTR(13);
|
|
MKINTR(14);
|
|
MKINTR(15);
|
|
MKINTR(16);
|
|
MKINTR(17);
|
|
MKINTR(18);
|
|
MKINTR(19);
|
|
MKINTR(20);
|
|
MKINTR(21);
|
|
MKINTR(22);
|
|
MKINTR(23);
|
|
MKINTR(24);
|
|
MKINTR(25);
|
|
MKINTR(26);
|
|
MKINTR(27);
|
|
MKINTR(28);
|
|
MKINTR(29);
|
|
MKINTR(30);
|
|
MKINTR(31);
|
|
MKINTR(32);
|
|
MKINTR(33);
|
|
MKINTR(34);
|
|
MKINTR(35);
|
|
MKINTR(36);
|
|
MKINTR(37);
|
|
MKINTR(38);
|
|
MKINTR(39);
|
|
MKINTR(40);
|
|
MKINTR(41);
|
|
MKINTR(42);
|
|
MKINTR(43);
|
|
MKINTR(44);
|
|
MKINTR(45);
|
|
MKINTR(46);
|
|
MKINTR(47);
|
|
|
|
extern void intr_vec128(void);
|
|
idt_setentry(0x80, (uint64_t)&intr_vec128, 0xEE);
|
|
|
|
idt_init();
|
|
}
|
|
|
|
void intr_dumpframe(IntrStackFrame *frame) {
|
|
uint64_t cr2;
|
|
asm volatile("mov %%cr2, %0" : "=r"(cr2));
|
|
uint64_t cr3;
|
|
asm volatile("mov %%cr3, %0" : "=r"(cr3));
|
|
uint64_t cr4;
|
|
asm volatile("mov %%cr4, %0" : "=r"(cr4));
|
|
kprintf("rax=%016lx rcx=%016lx rdx=%016lx\n"
|
|
"rsi=%016lx rdi=%016lx r8 =%016lx\n"
|
|
"r9 =%016lx r10=%016lx r11=%016lx\n"
|
|
"rip=%016lx rfl=%016lx rsp=%016lx\n"
|
|
"cs =%016lx ss =%016lx trp=%016lx\n"
|
|
"cr2=%016lx cr3=%016lx cr4=%016lx\n"
|
|
"\n\n",
|
|
frame->regs.rax, frame->regs.rcx, frame->regs.rdx,
|
|
frame->regs.rsi, frame->regs.rdi, frame->regs.r8,
|
|
frame->regs.r9, frame->regs.r10, frame->regs.r11,
|
|
frame->rip, frame->rflags, frame->rsp,
|
|
frame->cs, frame->ss, frame->trapnum,
|
|
cr2, cr3, cr4
|
|
);
|
|
}
|
|
|
|
void hal_syscalldispatch(IntrStackFrame *frame) {
|
|
uint64_t sysnum = frame->regs.rax;
|
|
if (sysnum < SYSCALLS_MAX) {
|
|
SyscallFn fn = SYSCALL_TABLE[sysnum];
|
|
if (fn == NULL) {
|
|
frame->regs.rax = E_BADSYSCALL;
|
|
return;
|
|
}
|
|
uint64_t cr3;
|
|
asm volatile("mov %%cr3, %0" : "=r"(cr3));
|
|
int32_t ret = fn(frame, frame->regs.rdi, frame->regs.rsi, frame->regs.rdx,
|
|
frame->regs.r10, frame->regs.r8, frame->regs.r9);
|
|
|
|
if (ret == E_DOSCHEDULING) {
|
|
proc_sched((void *)frame);
|
|
}
|
|
frame->regs.rax = *(uint64_t *)&ret;
|
|
}
|
|
}
|
|
|
|
void intr_eoi() {
|
|
io_out8(PIC2_CMD, PIC_EOI);
|
|
io_out8(PIC1_CMD, PIC_EOI);
|
|
}
|
|
|
|
void intr_handleintr(IntrStackFrame *frame) {
|
|
if (frame->trapnum <= 31) {
|
|
kprintf("ERROR %s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum);
|
|
intr_dumpframe(frame);
|
|
backtrace((BackTraceFrame *)frame->regs.rbp);
|
|
if (hal_vmm_current_cr3() != KERNEL_CR3) {
|
|
kprintf("killed pid %ld %s\n", PROCS.current->pid, PROCS.current->name);
|
|
proc_killself();
|
|
proc_sched((void *)frame);
|
|
}
|
|
hal_hang();
|
|
} else if (frame->trapnum >= 32 && frame->trapnum <= 47) {
|
|
switch (frame->trapnum) {
|
|
case INTR_IRQBASE+0:
|
|
PIT_TICKS++;
|
|
intr_eoi();
|
|
proc_sched((void *)frame);
|
|
break;
|
|
case INTR_IRQBASE+1:
|
|
int32_t c = ps2kb_intr();
|
|
if (c >= 0) {
|
|
uint8_t b = c;
|
|
spinlock_acquire(&PS2KB_BUF.spinlock);
|
|
rbuf_push(&PS2KB_BUF.rbuf, b);
|
|
spinlock_release(&PS2KB_BUF.spinlock);
|
|
}
|
|
intr_eoi();
|
|
break;
|
|
}
|
|
} else if (frame->trapnum == 0x80) {
|
|
hal_syscalldispatch(frame);
|
|
}
|
|
}
|
|
|