Interrupt handling/cpu exceptions
This commit is contained in:
@@ -14,5 +14,7 @@ void bootmain(void) {
|
|||||||
*a = 6969;
|
*a = 6969;
|
||||||
DEBUG("a=%p, *a=%d\n", a, *a);
|
DEBUG("a=%p, *a=%d\n", a, *a);
|
||||||
|
|
||||||
|
*(volatile int *)0 = 123;
|
||||||
|
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
cflags += --target=x86_64-pc-none-elf
|
cflags += --target=x86_64-pc-none-elf \
|
||||||
|
-mno-sse \
|
||||||
|
-mno-avx
|
||||||
|
|
||||||
ldflags += --target=x86_64-pc-none-elf \
|
ldflags += --target=x86_64-pc-none-elf \
|
||||||
-Wl,-zmax-page-size=0x1000
|
-Wl,-zmax-page-size=0x1000
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <amd64/init.h>
|
#include <amd64/init.h>
|
||||||
#include <amd64/tss.h>
|
#include <amd64/tss.h>
|
||||||
#include <amd64/debug.h>
|
#include <amd64/debug.h>
|
||||||
|
#include <amd64/intr.h>
|
||||||
|
|
||||||
#define GDT_KCODE 0x08
|
#define GDT_KCODE 0x08
|
||||||
#define GDT_KDATA 0x10
|
#define GDT_KDATA 0x10
|
||||||
@@ -102,4 +103,5 @@ static void amd64_gdt_init(void) {
|
|||||||
void amd64_init(void) {
|
void amd64_init(void) {
|
||||||
amd64_gdt_init();
|
amd64_gdt_init();
|
||||||
amd64_debug_init();
|
amd64_debug_init();
|
||||||
|
amd64_intr_init();
|
||||||
}
|
}
|
||||||
|
|||||||
157
kernel/amd64/intr.c
Normal file
157
kernel/amd64/intr.c
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
#include <libk/std.h>
|
||||||
|
#include <libk/string.h>
|
||||||
|
#include <sys/debug.h>
|
||||||
|
#include <amd64/intr.h>
|
||||||
|
#include <amd64/io.h>
|
||||||
|
|
||||||
|
/* 8259 PIC defs. */
|
||||||
|
#define PIC1 0x20
|
||||||
|
#define PIC2 0xA0
|
||||||
|
#define PIC1_CMD PIC1
|
||||||
|
#define PIC1_DATA (PIC1 + 1)
|
||||||
|
#define PIC2_CMD PIC2
|
||||||
|
#define PIC2_DATA (PIC2 + 1)
|
||||||
|
#define PIC_EOI 0x20
|
||||||
|
|
||||||
|
#define ICW1_ICW4 0x01
|
||||||
|
#define ICW1_SINGLE 0x02
|
||||||
|
#define ICW1_INTVL4 0x04
|
||||||
|
#define ICW1_LEVEL 0x08
|
||||||
|
#define ICW1_INIT 0x10
|
||||||
|
|
||||||
|
#define ICW4_8086 0x01
|
||||||
|
#define ICW4_AUTO 0x02
|
||||||
|
#define ICW4_BUFSLAVE 0x08
|
||||||
|
#define ICW4_BUFMASER 0x0C
|
||||||
|
#define ICW4_SFNM 0x10
|
||||||
|
|
||||||
|
#define CASCADE_IRQ 2
|
||||||
|
|
||||||
|
/* IDT defs. */
|
||||||
|
|
||||||
|
#define IDT_ENTRIES_MAX 256
|
||||||
|
|
||||||
|
struct idt_entry {
|
||||||
|
uint16_t intrlow;
|
||||||
|
uint16_t kernel_cs;
|
||||||
|
uint8_t ist;
|
||||||
|
uint8_t attrs;
|
||||||
|
uint16_t intrmid;
|
||||||
|
uint32_t intrhigh;
|
||||||
|
uint32_t resv;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct idt {
|
||||||
|
uint16_t limit;
|
||||||
|
uint64_t base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
__attribute__((aligned(16))) static volatile struct idt_entry idt_entries[IDT_ENTRIES_MAX];
|
||||||
|
static volatile struct idt idt;
|
||||||
|
|
||||||
|
extern void amd64_spin(void);
|
||||||
|
|
||||||
|
/* Remaps and disables old 8259 PIC, since we'll be using APIC. */
|
||||||
|
static void amd64_init_pic(void) {
|
||||||
|
#define IO_OP(fn, ...) fn(__VA_ARGS__); amd64_io_wait()
|
||||||
|
|
||||||
|
IO_OP(amd64_io_outb, PIC1_CMD, (ICW1_INIT | ICW1_ICW4));
|
||||||
|
IO_OP(amd64_io_outb, PIC2_CMD, (ICW1_INIT | ICW1_ICW4));
|
||||||
|
|
||||||
|
IO_OP(amd64_io_outb, PIC1_DATA, 0x20);
|
||||||
|
IO_OP(amd64_io_outb, PIC2_DATA, 0x28);
|
||||||
|
|
||||||
|
IO_OP(amd64_io_outb, PIC1_DATA, (1 << CASCADE_IRQ));
|
||||||
|
IO_OP(amd64_io_outb, PIC2_DATA, 2);
|
||||||
|
|
||||||
|
IO_OP(amd64_io_outb, PIC1_DATA, ICW4_8086);
|
||||||
|
IO_OP(amd64_io_outb, PIC2_DATA, ICW4_8086);
|
||||||
|
|
||||||
|
/* Disable */
|
||||||
|
IO_OP(amd64_io_outb, PIC1_DATA, 0xFF);
|
||||||
|
IO_OP(amd64_io_outb, PIC2_DATA, 0xFF);
|
||||||
|
|
||||||
|
#undef IO_OP
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd64_idt_set(volatile struct idt_entry *ent, uint64_t handler, uint8_t flags) {
|
||||||
|
ent->intrlow = (handler & 0xFFFF);
|
||||||
|
ent->kernel_cs = 0x08; // GDT_KCODE (init.c)
|
||||||
|
ent->ist = 0;
|
||||||
|
ent->attrs = flags;
|
||||||
|
ent->intrmid = ((handler >> 16) & 0xFFFF);
|
||||||
|
ent->intrhigh = ((handler >> 32) & 0xFFFFFFFF);
|
||||||
|
ent->resv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd64_idt_init(void) {
|
||||||
|
memset((void *)idt_entries, 0, sizeof(idt_entries));
|
||||||
|
|
||||||
|
#define IDT_ENTRY(n) \
|
||||||
|
extern void amd64_intr ## n(void); \
|
||||||
|
amd64_idt_set(&idt_entries[(n)], (uint64_t)&amd64_intr ## n, 0x8E)
|
||||||
|
IDT_ENTRY(0); IDT_ENTRY(1); IDT_ENTRY(2); IDT_ENTRY(3);
|
||||||
|
IDT_ENTRY(4); IDT_ENTRY(5); IDT_ENTRY(6); IDT_ENTRY(7);
|
||||||
|
IDT_ENTRY(8); IDT_ENTRY(9); IDT_ENTRY(10); IDT_ENTRY(11);
|
||||||
|
IDT_ENTRY(12); IDT_ENTRY(13); IDT_ENTRY(14); IDT_ENTRY(15);
|
||||||
|
IDT_ENTRY(16); IDT_ENTRY(17); IDT_ENTRY(18); IDT_ENTRY(19);
|
||||||
|
IDT_ENTRY(20); IDT_ENTRY(21); IDT_ENTRY(22); IDT_ENTRY(23);
|
||||||
|
IDT_ENTRY(24); IDT_ENTRY(25); IDT_ENTRY(26); IDT_ENTRY(27);
|
||||||
|
IDT_ENTRY(28); IDT_ENTRY(29); IDT_ENTRY(30); IDT_ENTRY(31);
|
||||||
|
IDT_ENTRY(32); IDT_ENTRY(33); IDT_ENTRY(34); IDT_ENTRY(35);
|
||||||
|
IDT_ENTRY(36); IDT_ENTRY(37); IDT_ENTRY(38); IDT_ENTRY(39);
|
||||||
|
IDT_ENTRY(40); IDT_ENTRY(41); IDT_ENTRY(42); IDT_ENTRY(43);
|
||||||
|
IDT_ENTRY(44); IDT_ENTRY(45); IDT_ENTRY(46); IDT_ENTRY(47);
|
||||||
|
#undef IDT_ENTRY
|
||||||
|
|
||||||
|
idt.limit = sizeof(idt_entries) - 1;
|
||||||
|
idt.base = (uint64_t)idt_entries;
|
||||||
|
|
||||||
|
__asm__ volatile("lidt %0" :: "m"(idt));
|
||||||
|
__asm__ volatile("sti");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd64_intr_exception(struct saved_regs *regs) {
|
||||||
|
DEBUG("cpu exception %lu (%lu)\n", regs->trap, regs->error);
|
||||||
|
|
||||||
|
uint64_t cr2;
|
||||||
|
__asm__ volatile("movq %%cr2, %0" : "=r"(cr2));
|
||||||
|
uint64_t cr3;
|
||||||
|
__asm__ volatile("movq %%cr3, %0" : "=r"(cr3));
|
||||||
|
|
||||||
|
debugprintf(
|
||||||
|
"r15=%016lx r14=%016lx r13=%016lx\n"
|
||||||
|
"r12=%016lx r11=%016lx r10=%016lx\n"
|
||||||
|
"r9 =%016lx r8 =%016lx rbp=%016lx\n"
|
||||||
|
"rdi=%016lx rsi=%016lx rdx=%016lx\n"
|
||||||
|
"rcx=%016lx rax=%016lx trp=%016lx\n"
|
||||||
|
"err=%016lx rip=%016lx cs =%016lx\n"
|
||||||
|
"rfl=%016lx rsp=%016lx ss =%016lx\n"
|
||||||
|
"cr2=%016lx cr3=%016lx rbx=%016lx\n",
|
||||||
|
regs->r15, regs->r14, regs->r13,
|
||||||
|
regs->r12, regs->r11, regs->r10,
|
||||||
|
regs->r9, regs->r8, regs->rbp,
|
||||||
|
regs->rdi, regs->rsi, regs->rdx,
|
||||||
|
regs->rcx, regs->rax, regs->trap,
|
||||||
|
regs->error, regs->rip, regs->cs,
|
||||||
|
regs->rflags, regs->rsp, regs->ss,
|
||||||
|
cr2, cr3, regs->rbx
|
||||||
|
);
|
||||||
|
|
||||||
|
amd64_spin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_intr_handler(void *stack_ptr) {
|
||||||
|
struct saved_regs *regs = stack_ptr;
|
||||||
|
|
||||||
|
if (regs->trap <= 31) {
|
||||||
|
amd64_intr_exception(regs);
|
||||||
|
} else {
|
||||||
|
DEBUG("unknown trap %lu\n", regs->trap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_intr_init(void) {
|
||||||
|
amd64_init_pic();
|
||||||
|
amd64_idt_init();
|
||||||
|
}
|
||||||
35
kernel/amd64/intr.h
Normal file
35
kernel/amd64/intr.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef _KERNEL_AMD64_INTR_H
|
||||||
|
#define _KERNEL_AMD64_INTR_H
|
||||||
|
|
||||||
|
#include <libk/std.h>
|
||||||
|
|
||||||
|
struct saved_regs {
|
||||||
|
/* regs */
|
||||||
|
uint64_t r15;
|
||||||
|
uint64_t r14;
|
||||||
|
uint64_t r13;
|
||||||
|
uint64_t r12;
|
||||||
|
uint64_t r11;
|
||||||
|
uint64_t r10;
|
||||||
|
uint64_t r9;
|
||||||
|
uint64_t r8;
|
||||||
|
uint64_t rbx;
|
||||||
|
uint64_t rbp;
|
||||||
|
uint64_t rdi;
|
||||||
|
uint64_t rsi;
|
||||||
|
uint64_t rdx;
|
||||||
|
uint64_t rcx;
|
||||||
|
uint64_t rax;
|
||||||
|
/* interrupt stuff */
|
||||||
|
uint64_t trap;
|
||||||
|
uint64_t error;
|
||||||
|
uint64_t rip;
|
||||||
|
uint64_t cs;
|
||||||
|
uint64_t rflags;
|
||||||
|
uint64_t rsp;
|
||||||
|
uint64_t ss;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void amd64_intr_init(void);
|
||||||
|
|
||||||
|
#endif // _KERNEL_AMD64_INTR_H
|
||||||
110
kernel/amd64/intr_stub.S
Normal file
110
kernel/amd64/intr_stub.S
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
.extern amd64_intr_handler
|
||||||
|
|
||||||
|
dupa:
|
||||||
|
jmp dupa
|
||||||
|
|
||||||
|
#define err(z) \
|
||||||
|
pushq $z;
|
||||||
|
|
||||||
|
#define no_err(z) \
|
||||||
|
pushq $0; \
|
||||||
|
pushq $z;
|
||||||
|
|
||||||
|
#define push_regs \
|
||||||
|
pushq %rax; \
|
||||||
|
pushq %rcx; \
|
||||||
|
pushq %rdx; \
|
||||||
|
pushq %rsi; \
|
||||||
|
pushq %rdi; \
|
||||||
|
pushq %rbp; \
|
||||||
|
pushq %rbx; \
|
||||||
|
pushq %r8; \
|
||||||
|
pushq %r9; \
|
||||||
|
pushq %r10; \
|
||||||
|
pushq %r11; \
|
||||||
|
pushq %r12; \
|
||||||
|
pushq %r13; \
|
||||||
|
pushq %r14; \
|
||||||
|
pushq %r15;
|
||||||
|
|
||||||
|
#define pop_regs \
|
||||||
|
popq %r15; \
|
||||||
|
popq %r14; \
|
||||||
|
popq %r13; \
|
||||||
|
popq %r12; \
|
||||||
|
popq %r11; \
|
||||||
|
popq %r10; \
|
||||||
|
popq %r9; \
|
||||||
|
popq %r8; \
|
||||||
|
pushq %rbx; \
|
||||||
|
popq %rbp; \
|
||||||
|
popq %rdi; \
|
||||||
|
popq %rsi; \
|
||||||
|
popq %rdx; \
|
||||||
|
popq %rcx; \
|
||||||
|
popq %rax;
|
||||||
|
|
||||||
|
#define make_intr_stub(x, n) \
|
||||||
|
.global amd64_intr ## n; \
|
||||||
|
amd64_intr ## n:; \
|
||||||
|
x(n); \
|
||||||
|
cli; \
|
||||||
|
push_regs; \
|
||||||
|
cld; \
|
||||||
|
movq %rsp, %rdi; \
|
||||||
|
andq $~0xF, %rsp; \
|
||||||
|
callq amd64_intr_handler; \
|
||||||
|
movq %rdi, %rsp; \
|
||||||
|
pop_regs; \
|
||||||
|
addq $16, %rsp; \
|
||||||
|
iretq;
|
||||||
|
|
||||||
|
|
||||||
|
make_intr_stub(no_err, 0)
|
||||||
|
make_intr_stub(no_err, 1)
|
||||||
|
make_intr_stub(no_err, 2)
|
||||||
|
make_intr_stub(no_err, 3)
|
||||||
|
make_intr_stub(no_err, 4)
|
||||||
|
make_intr_stub(no_err, 5)
|
||||||
|
make_intr_stub(no_err, 6)
|
||||||
|
make_intr_stub(no_err, 7)
|
||||||
|
make_intr_stub(err, 8)
|
||||||
|
make_intr_stub(no_err, 9)
|
||||||
|
make_intr_stub(err, 10)
|
||||||
|
make_intr_stub(err, 11)
|
||||||
|
make_intr_stub(err, 12)
|
||||||
|
make_intr_stub(err, 13)
|
||||||
|
make_intr_stub(err, 14)
|
||||||
|
make_intr_stub(no_err, 15)
|
||||||
|
make_intr_stub(no_err, 16)
|
||||||
|
make_intr_stub(err, 17)
|
||||||
|
make_intr_stub(no_err, 18)
|
||||||
|
make_intr_stub(no_err, 19)
|
||||||
|
make_intr_stub(no_err, 20)
|
||||||
|
make_intr_stub(err, 21)
|
||||||
|
make_intr_stub(no_err, 22)
|
||||||
|
make_intr_stub(no_err, 23)
|
||||||
|
make_intr_stub(no_err, 24)
|
||||||
|
make_intr_stub(no_err, 25)
|
||||||
|
make_intr_stub(no_err, 26)
|
||||||
|
make_intr_stub(no_err, 27)
|
||||||
|
make_intr_stub(no_err, 28)
|
||||||
|
make_intr_stub(err, 29)
|
||||||
|
make_intr_stub(err, 30)
|
||||||
|
make_intr_stub(no_err, 31)
|
||||||
|
make_intr_stub(no_err, 32)
|
||||||
|
make_intr_stub(no_err, 33)
|
||||||
|
make_intr_stub(no_err, 34)
|
||||||
|
make_intr_stub(no_err, 35)
|
||||||
|
make_intr_stub(no_err, 36)
|
||||||
|
make_intr_stub(no_err, 37)
|
||||||
|
make_intr_stub(no_err, 38)
|
||||||
|
make_intr_stub(no_err, 39)
|
||||||
|
make_intr_stub(no_err, 40)
|
||||||
|
make_intr_stub(no_err, 41)
|
||||||
|
make_intr_stub(no_err, 42)
|
||||||
|
make_intr_stub(no_err, 43)
|
||||||
|
make_intr_stub(no_err, 44)
|
||||||
|
make_intr_stub(no_err, 45)
|
||||||
|
make_intr_stub(no_err, 46)
|
||||||
|
make_intr_stub(no_err, 47)
|
||||||
3
kernel/amd64/spin.S
Normal file
3
kernel/amd64/spin.S
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.global amd64_spin
|
||||||
|
amd64_spin:
|
||||||
|
jmp amd64_spin
|
||||||
@@ -3,11 +3,18 @@ c += amd64/bootmain.c \
|
|||||||
amd64/tss.c \
|
amd64/tss.c \
|
||||||
amd64/io.c \
|
amd64/io.c \
|
||||||
amd64/debug.c \
|
amd64/debug.c \
|
||||||
amd64/spin_lock.c
|
amd64/spin_lock.c \
|
||||||
|
amd64/intr.c
|
||||||
|
|
||||||
|
S += amd64/intr_stub.S \
|
||||||
|
amd64/spin.S
|
||||||
|
|
||||||
o += amd64/bootmain.o \
|
o += amd64/bootmain.o \
|
||||||
amd64/init.o \
|
amd64/init.o \
|
||||||
amd64/tss.o \
|
amd64/tss.o \
|
||||||
amd64/io.o \
|
amd64/io.o \
|
||||||
amd64/debug.o \
|
amd64/debug.o \
|
||||||
amd64/spin_lock.o
|
amd64/spin_lock.o \
|
||||||
|
amd64/intr.o \
|
||||||
|
amd64/intr_stub.o \
|
||||||
|
amd64/spin.o
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef _KERNEL_LIBK_PRINTF_CONFIG_H
|
#ifndef _KERNEL_LIBK_PRINTF_CONFIG_H
|
||||||
#define _KERNEL_LIBK_PRINTF_CONFIG_H
|
#define _KERNEL_LIBK_PRINTF_CONFIG_H
|
||||||
|
|
||||||
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD 1
|
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD 1
|
||||||
|
#define PRINTF_SUPPORT_DECIMAL_SPECIFIERS 0
|
||||||
|
#define PRINTF_SUPPORT_EXPONENTIAL_SPECIFIERS 0
|
||||||
|
|
||||||
#endif // _KERNEL_LIBK_PRINTF_CONFIG_H
|
#endif // _KERNEL_LIBK_PRINTF_CONFIG_H
|
||||||
|
|||||||
Reference in New Issue
Block a user