diff --git a/kernel/amd64/bootmain.c b/kernel/amd64/bootmain.c index 7a14c65..0e6e1cc 100644 --- a/kernel/amd64/bootmain.c +++ b/kernel/amd64/bootmain.c @@ -14,5 +14,7 @@ void bootmain(void) { *a = 6969; DEBUG("a=%p, *a=%d\n", a, *a); + *(volatile int *)0 = 123; + for (;;); } diff --git a/kernel/amd64/flags.mk b/kernel/amd64/flags.mk index 62b72cb..707c344 100644 --- a/kernel/amd64/flags.mk +++ b/kernel/amd64/flags.mk @@ -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 \ -Wl,-zmax-page-size=0x1000 diff --git a/kernel/amd64/init.c b/kernel/amd64/init.c index 3a1b6ad..a45cf4f 100644 --- a/kernel/amd64/init.c +++ b/kernel/amd64/init.c @@ -3,6 +3,7 @@ #include #include #include +#include #define GDT_KCODE 0x08 #define GDT_KDATA 0x10 @@ -102,4 +103,5 @@ static void amd64_gdt_init(void) { void amd64_init(void) { amd64_gdt_init(); amd64_debug_init(); + amd64_intr_init(); } diff --git a/kernel/amd64/intr.c b/kernel/amd64/intr.c new file mode 100644 index 0000000..ce48ebc --- /dev/null +++ b/kernel/amd64/intr.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include +#include + +/* 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(); +} diff --git a/kernel/amd64/intr.h b/kernel/amd64/intr.h new file mode 100644 index 0000000..294821f --- /dev/null +++ b/kernel/amd64/intr.h @@ -0,0 +1,35 @@ +#ifndef _KERNEL_AMD64_INTR_H +#define _KERNEL_AMD64_INTR_H + +#include + +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 diff --git a/kernel/amd64/intr_stub.S b/kernel/amd64/intr_stub.S new file mode 100644 index 0000000..2885727 --- /dev/null +++ b/kernel/amd64/intr_stub.S @@ -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) diff --git a/kernel/amd64/spin.S b/kernel/amd64/spin.S new file mode 100644 index 0000000..916c750 --- /dev/null +++ b/kernel/amd64/spin.S @@ -0,0 +1,3 @@ +.global amd64_spin +amd64_spin: + jmp amd64_spin diff --git a/kernel/amd64/src.mk b/kernel/amd64/src.mk index 51e6596..1665801 100644 --- a/kernel/amd64/src.mk +++ b/kernel/amd64/src.mk @@ -3,11 +3,18 @@ c += amd64/bootmain.c \ amd64/tss.c \ amd64/io.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 \ amd64/init.o \ amd64/tss.o \ amd64/io.o \ amd64/debug.o \ - amd64/spin_lock.o + amd64/spin_lock.o \ + amd64/intr.o \ + amd64/intr_stub.o \ + amd64/spin.o diff --git a/kernel/libk/printf_config.h b/kernel/libk/printf_config.h index 127e3ef..fcf83d1 100644 --- a/kernel/libk/printf_config.h +++ b/kernel/libk/printf_config.h @@ -1,6 +1,8 @@ #ifndef _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