diff --git a/kernel/compiler/attr.h b/kernel/compiler/attr.h index e4e262f..2877b0b 100644 --- a/kernel/compiler/attr.h +++ b/kernel/compiler/attr.h @@ -2,5 +2,6 @@ #define COMPILER_ATTR_H_ #define PACKED __attribute__((packed)) +#define ALIGNED(x) __attribute__((aligned((x)))) #endif // COMPILER_ATTR_H_ diff --git a/kernel/hal/x86_64/acpi.c b/kernel/hal/x86_64/acpi.c index d928f1e..25e4bf6 100644 --- a/kernel/hal/x86_64/acpi.c +++ b/kernel/hal/x86_64/acpi.c @@ -8,6 +8,8 @@ #define PREINIT_BUFFER_SIZE 0x1000 +struct acpi_madt *MADT; + void acpi_init(void) { uacpi_status ret; @@ -18,15 +20,5 @@ void acpi_init(void) { hal_hang(); } - /* if (uacpi_unlikely_error(ret)) { */ - /* ERR("acpi", "init err %s\n", uacpi_status_to_string(ret)); */ - /* hal_hang(); */ - /* } */ - - /* if (uacpi_unlikely_error(ret)) { */ - /* ERR("acpi", "init err %s\n", uacpi_status_to_string(ret)); */ - /* hal_hang(); */ - /* } */ - LOG("hal", "acpi init\n"); } diff --git a/kernel/hal/x86_64/acpi.h b/kernel/hal/x86_64/acpi.h index 9e6181c..f90366f 100644 --- a/kernel/hal/x86_64/acpi.h +++ b/kernel/hal/x86_64/acpi.h @@ -1,6 +1,10 @@ #ifndef HAL_ACPI_H_ #define HAL_ACPI_H_ +#include "uacpi/uacpi.h" + +extern struct acpi_madt *MADT; + void acpi_init(void); #endif // HAL_ACPI_H_ diff --git a/kernel/hal/x86_64/cpu.c b/kernel/hal/x86_64/cpu.c new file mode 100644 index 0000000..9b9077d --- /dev/null +++ b/kernel/hal/x86_64/cpu.c @@ -0,0 +1,14 @@ +#include +#include + +uint64_t cpu_rdmsr(uint32_t id) { + uint32_t lo, hi; + asm volatile("rdmsr" : "=m"(lo), "=d"(hi) : "c"(id)); + return ((uint64_t)lo) | ((uint64_t)hi << 32); +} + +uint64_t cpu_wrmsr(uint32_t id, uint64_t val) { + uint32_t lo = val & 0xffffffff, hi = (val >> 32) & 0xffffffff; + asm volatile("wrmsr" :: "a"(lo), "d"(hi), "c"(id) : "memory"); + return val; +} diff --git a/kernel/hal/x86_64/cpu.h b/kernel/hal/x86_64/cpu.h new file mode 100644 index 0000000..ae92118 --- /dev/null +++ b/kernel/hal/x86_64/cpu.h @@ -0,0 +1,7 @@ +#ifndef HAL_CPU_H_ +#define HAL_CPU_H_ + +uint64_t cpu_rdmsr(uint32_t id); +uint64_t cpu_wrmsr(uint32_t id, uint64_t val); + +#endif // HAL_CPU_H_ diff --git a/kernel/hal/x86_64/gdt.c b/kernel/hal/x86_64/gdt.c index be33c07..61259db 100644 --- a/kernel/hal/x86_64/gdt.c +++ b/kernel/hal/x86_64/gdt.c @@ -2,8 +2,18 @@ #include #include "compiler/attr.h" #include "hal/hal.h" +#include "gdt.h" #define GDT_SIZE 5 +#define GDT_PRESENT 0x80 +#define GDT_TSS 0x89 + +#define KSTACK 8192 +ALIGNED(16) static uint8_t kernelstack[KSTACK]; + +#define ISTS 7 +#define ISTACK 4096 +ALIGNED(16) static uint8_t iststacks[ISTS][ISTACK]; typedef struct { uint16_t limitlow; @@ -31,64 +41,73 @@ typedef struct { uint64_t rsp1; uint64_t rsp2; uint64_t resv1; - uint64_t ist[7]; + uint64_t ist[ISTS]; uint64_t resv2; uint16_t resv3; uint16_t iopb_off; } PACKED Tss; -static Tss tss = {0}; -static ExtendedGdt *curgdt = NULL; +ALIGNED(16) static Tss tss = {0}; +ALIGNED(16) static ExtendedGdt gdt = {0}; -#define KCODE 0x08 -#define KDATA 0x10 -#define UCODE 0x18 -#define UDATA 0x20 -#define TSS 0x28 - -#define GDT_PRESENT 0x80 -#define GDT_TSS 0x89 - -static uint64_t gdt_curretbase(void) { - GdtPtr gdtr; - asm volatile("sgdt %0" : "=m"(gdtr)); - return gdtr.base; -} - -void gdt_setentry(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { - entry->baselow = base & 0xffff; - entry->basemid = (base >> 16) & 0xff; - entry->basehigh = (base >> 24) & 0xff; - entry->limitlow = limit & 0xffff; - entry->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0); - entry->access = access; +void gdt_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint32_t acc, uint8_t gran) { + ent->baselow = base & 0xffff; + ent->basemid = (base >> 16) & 0xff; + ent->basehigh = (base >> 24) & 0xff; + ent->limitlow = limit & 0xffff; + ent->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0); + ent->access = acc; } void gdt_init(void) { - uint64_t base = gdt_curretbase(); - curgdt = (ExtendedGdt *)base; - hal_memset(&tss, 0, sizeof(tss)); tss.iopb_off = sizeof(tss); + tss.rsp0 = (uint64_t)(kernelstack + sizeof(kernelstack)); + + for (size_t i = 0; i < ISTS; i++) { + tss.ist[i] = (uint64_t)(iststacks[i] + sizeof(iststacks[i])); + } + uint64_t tss_base = (uint64_t)&tss; uint32_t tss_limit = sizeof(tss) - 1; - gdt_setentry(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0); - - GdtEntry *tsshigh = &curgdt->tsshigh; - tsshigh->baselow = (tss_base >> 32) & 0xffff; - tsshigh->basemid = (tss_base >> 48) & 0xff; - tsshigh->basehigh = (tss_base >> 56) & 0xff; - tsshigh->access = 0; - tsshigh->gran = 0; - tsshigh->limitlow = 0; + gdt_setentry(&gdt.old[0], 0, 0, 0, 0); + gdt_setentry(&gdt.old[1], 0, 0xFFFFF, 0x9a, 0xA0); + gdt_setentry(&gdt.old[2], 0, 0xFFFFF, 0x92, 0xA0); + gdt_setentry(&gdt.old[3], 0, 0xFFFFF, 0xfa, 0xA0); + gdt_setentry(&gdt.old[4], 0, 0xFFFFF, 0xf2, 0xA0); + + gdt_setentry(&gdt.tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0); + + uint32_t tssbasehi = tss_base >> 32; + gdt.tsshigh.limitlow = tssbasehi & 0xffff; + gdt.tsshigh.baselow = (tssbasehi >> 16) & 0xffff; + gdt.tsshigh.basemid = 0; + gdt.tsshigh.basehigh = 0; + gdt.tsshigh.access = 0; + gdt.tsshigh.gran = 0; GdtPtr gdtr; - asm volatile("sgdt %0" : "=m"(gdtr)); - gdtr.limit = sizeof(ExtendedGdt) - 1; + gdtr.limit = sizeof(gdt) - 1; + gdtr.base = (uint64_t)&gdt; asm volatile("lgdt %0" :: "m"(gdtr)); - asm volatile("ltr %0" :: "r"((uint16_t)0x28)); + asm volatile( + "pushq %[kcode]\n" + "lea 1f(%%rip), %%rax\n" + "pushq %%rax\n" + "lretq\n" + "1:\n" + "movw %[kdata], %%ax\n" + "movw %%ax, %%ds\n" + "movw %%ax, %%es\n" + "movw %%ax, %%ss\n" + : + : [kcode] "i"(KCODE), [kdata] "i"(KDATA) + : "rax", "memory" + ); + + asm volatile("ltr %0" :: "r"((uint16_t)TSS)); } diff --git a/kernel/hal/x86_64/gdt.h b/kernel/hal/x86_64/gdt.h index 529a124..1128154 100644 --- a/kernel/hal/x86_64/gdt.h +++ b/kernel/hal/x86_64/gdt.h @@ -1,6 +1,12 @@ #ifndef HAL_GDT_H_ #define HAL_GDT_H_ +#define KCODE 0x08 +#define KDATA 0x10 +#define UCODE 0x18 +#define UDATA 0x20 +#define TSS 0x28 + void gdt_init(void); #endif // HAL_GDT_H_ diff --git a/kernel/hal/x86_64/hal.c b/kernel/hal/x86_64/hal.c index 8b550eb..8c87ea6 100644 --- a/kernel/hal/x86_64/hal.c +++ b/kernel/hal/x86_64/hal.c @@ -4,8 +4,8 @@ #include "kprintf.h" #include "serial.h" #include "gdt.h" -#include "idt.h" #include "acpi.h" +#include "isr.h" void hal_init(void) { if (!serial_init()) { @@ -22,6 +22,7 @@ __attribute__((noreturn)) void hal_hang(void) { } void hal_init_withmalloc(void) { - acpi_init(); + /* acpi_init(); */ + isr_init(); } diff --git a/kernel/hal/x86_64/idt.c b/kernel/hal/x86_64/idt.c deleted file mode 100644 index ea0828f..0000000 --- a/kernel/hal/x86_64/idt.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "idt.h" -#include "kprintf.h" - -#define ENTRIES 256 -static IdtGate idtgates[ENTRIES] = {0}; -static Idt idt; - -void idt_setgate(int i, uint64_t handler, uint8_t flags) { - idtgates[i].isrlow = (uint16_t)handler; - idtgates[i].kernelcs = 40; - idtgates[i].ist = 0; - idtgates[i].resv = 0; - idtgates[i].attrs = flags; - idtgates[i].isrmid = (uint16_t)(handler >> 16); - idtgates[i].isrhigh = (uint16_t)(handler >> 32); -} - -void idt_init(void) { - idt.base = (uint64_t)&idtgates; - idt.limit = ENTRIES * sizeof(IdtGate) - 1; - asm volatile("lidt %0" :: "m"(idt) : "memory"); - - LOG("idt", "idt init\n"); -} diff --git a/kernel/hal/x86_64/idt.h b/kernel/hal/x86_64/idt.h deleted file mode 100644 index e5cc944..0000000 --- a/kernel/hal/x86_64/idt.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef HAL_IDT_H_ -#define HAL_IDT_H_ - -#include -#include "compiler/attr.h" - -typedef struct { - uint16_t isrlow; - uint16_t kernelcs; - uint8_t ist; - uint8_t attrs; - uint16_t isrmid; - uint32_t isrhigh; - uint32_t resv; -} PACKED IdtGate; - -typedef struct { - uint16_t limit; - uint64_t base; -} PACKED Idt; - -void idt_init(void); - -#endif // HAL_IDT_H_ diff --git a/kernel/hal/x86_64/isr.c b/kernel/hal/x86_64/isr.c new file mode 100644 index 0000000..aa589d4 --- /dev/null +++ b/kernel/hal/x86_64/isr.c @@ -0,0 +1,176 @@ +#include +#include +#include "isr.h" +#include "io.h" +#include "gdt.h" +#include "hal/hal.h" +#include "kprintf.h" +#include "compiler/attr.h" + +typedef struct { + uint16_t isrlow; + uint16_t kernelcs; + uint8_t ist; + uint8_t attrs; + uint16_t isrmid; + uint32_t isrhigh; + 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 ist, uint8_t flags) { + idtgates[i].isrlow = handler & 0xffff; + idtgates[i].kernelcs = KCODE; + idtgates[i].ist = ist; + idtgates[i].attrs = flags; + idtgates[i].isrmid = (handler >> 16) & 0xFFFF; + idtgates[i].isrhigh = (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("idt", "idt init\n"); +} + +typedef struct { + 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 rsi; + uint64_t rdi; + uint64_t rbp; + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; +} PACKED CpuRegs; + +typedef struct { + uint64_t cr8; + uint64_t cr4; + uint64_t cr3; + uint64_t cr2; + uint64_t cr0; +} PACKED CpuCtrlRegs; + +typedef struct { + CpuCtrlRegs ctrl; + CpuRegs regs; + uint64_t trapnum; + uint64_t errnum; + + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +} PACKED IntrStackFrame; + +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", +}; + +extern void isr_vec0(void); +extern void isr_vec1(void); +extern void isr_vec2(void); +extern void isr_vec3(void); +extern void isr_vec4(void); +extern void isr_vec5(void); +extern void isr_vec6(void); +extern void isr_vec7(void); +extern void isr_vec8(void); +extern void isr_vec10(void); +extern void isr_vec11(void); +extern void isr_vec12(void); +extern void isr_vec13(void); +extern void isr_vec14(void); +extern void isr_vec16(void); +extern void isr_vec17(void); +extern void isr_vec18(void); +extern void isr_vec19(void); +extern void isr_vec20(void); +extern void isr_vec21(void); +extern void isr_vec32(void); +extern void isr_vec33(void); +extern void isr_vec39(void); + +void isr_init(void) { + idt_setentry(0, (uint64_t)&isr_vec0, 0, 0x8E); + idt_setentry(1, (uint64_t)&isr_vec1, 0, 0x8E); + idt_setentry(2, (uint64_t)&isr_vec2, 2, 0x8E); + idt_setentry(3, (uint64_t)&isr_vec3, 0, 0x8E); + idt_setentry(4, (uint64_t)&isr_vec4, 0, 0x8E); + idt_setentry(5, (uint64_t)&isr_vec5, 0, 0x8E); + idt_setentry(6, (uint64_t)&isr_vec6, 0, 0x8E); + idt_setentry(7, (uint64_t)&isr_vec7, 0, 0x8E); + idt_setentry(8, (uint64_t)&isr_vec8, 1, 0x8E); + idt_setentry(10, (uint64_t)&isr_vec10, 0, 0x8E); + idt_setentry(11, (uint64_t)&isr_vec11, 0, 0x8E); + idt_setentry(12, (uint64_t)&isr_vec12, 0, 0x8E); + idt_setentry(13, (uint64_t)&isr_vec13, 0, 0x8E); + idt_setentry(14, (uint64_t)&isr_vec14, 0, 0x8E); + idt_setentry(16, (uint64_t)&isr_vec16, 0, 0x8E); + idt_setentry(17, (uint64_t)&isr_vec17, 0, 0x8E); + idt_setentry(18, (uint64_t)&isr_vec18, 0, 0x8E); + idt_setentry(19, (uint64_t)&isr_vec19, 0, 0x8E); + idt_setentry(20, (uint64_t)&isr_vec20, 0, 0x8E); + idt_setentry(21, (uint64_t)&isr_vec21, 0, 0x8E); + idt_setentry(32, (uint64_t)&isr_vec32, 0, 0x8E); + idt_setentry(33, (uint64_t)&isr_vec33, 0, 0x8E); + idt_setentry(39, (uint64_t)&isr_vec39, 0, 0x8E); + + idt_init(); +} + +void isr_dumpframe(IntrStackFrame *frame) { + kprintf("r15=%016llx r14=%016llx r13=%016llx r12=%016llx\n" + "r11=%016llx r10=%016llx r9 =%016llx r8 =%016llx\n" + "rsi=%016llx rdi=%016llx rbp=%016llx rdx=%016llx\n" + "rcx=%016llx rbx=%016llx rax=%016llx\n" + "cr8=%016llx cr4=%016llx cr3=%016llx cr2=%016llx\n" + "cr0=%016llx rip=%016llx cs =%016llx rfl=%016llx\n" + "rsp=%016llx ss =%016llx trp=%016llx err=%016llx\n", + frame->regs.r15, frame->regs.r14, frame->regs.r13, frame->regs.r12, + frame->regs.r11, frame->regs.r10, frame->regs.r9, frame->regs.r8, + frame->regs.rsi, frame->regs.rdi, frame->regs.rbp, frame->regs.rdx, + frame->regs.rcx, frame->regs.rbx, frame->regs.rax, + frame->ctrl.cr8, frame->ctrl.cr4, frame->ctrl.cr3, + frame->ctrl.cr2, frame->ctrl.cr0, frame->rip, frame->cs, frame->rflags, + frame->rsp, frame->ss, frame->trapnum, frame->errnum + + ); +} + +void isr_handleintr(IntrStackFrame *frame) { + hal_intr_disable(); + ERR("ERROR", "%s, 0x%X\n", exceptions[frame->trapnum], frame->errnum); + isr_dumpframe(frame); + hal_hang(); +} + diff --git a/kernel/hal/x86_64/isr.h b/kernel/hal/x86_64/isr.h new file mode 100644 index 0000000..02bab1f --- /dev/null +++ b/kernel/hal/x86_64/isr.h @@ -0,0 +1,6 @@ +#ifndef HAL_ISR_H_ +#define HAL_ISR_H_ + +void isr_init(void); + +#endif // HAL_ISR_H_ diff --git a/kernel/hal/x86_64/isr0.S b/kernel/hal/x86_64/isr0.S new file mode 100644 index 0000000..318ec96 --- /dev/null +++ b/kernel/hal/x86_64/isr0.S @@ -0,0 +1,175 @@ +.extern isr_handleintr + +.global isr_vec0 +.global isr_vec1 +.global isr_vec2 +.global isr_vec3 +.global isr_vec4 +.global isr_vec5 +.global isr_vec6 +.global isr_vec7 +.global isr_vec8 +.global isr_vec10 +.global isr_vec11 +.global isr_vec12 +.global isr_vec13 +.global isr_vec14 +.global isr_vec16 +.global isr_vec17 +.global isr_vec18 +.global isr_vec19 +.global isr_vec20 +.global isr_vec21 +.global isr_vec32 +.global isr_vec33 +.global isr_vec39 + +.macro _PUSHAQ + push %rax + push %rbx + push %rcx + push %rdx + push %rbp + push %rdi + push %rsi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 +.endm + +.macro _POPAQ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rsi + pop %rdi + pop %rbp + pop %rdx + pop %rcx + pop %rbx + pop %rax +.endm + +.macro _PUSHACR + mov %cr0, %rax + push %rax + + mov %cr2, %rax + push %rax + + mov %cr3, %rax + push %rax + + mov %cr4, %rax + push %rax + + mov %cr8, %rax + push %rax +.endm + +.macro _vecintr_errorcode_present_save num + push $\num + _PUSHAQ + _PUSHACR +.endm + +.macro _vecintr_plain_save num errorno + push $\errorno + push $\num + _PUSHAQ + _PUSHACR +.endm + +.macro _vecintr_restore + add 40, %rsp + _POPAQ + add 16, %rsp +.endm + +.macro _vecintr_bodygen + cld + mov %rsp, %rdi + call isr_handleintr + _vecintr_restore + iretq +.endm + +isr_vec0: + _vecintr_plain_save 0, 0 + _vecintr_bodygen +isr_vec1: + _vecintr_plain_save 1, 0 + _vecintr_bodygen +isr_vec2: + _vecintr_plain_save 2, 0 + _vecintr_bodygen +isr_vec3: + _vecintr_plain_save 3, 0 + _vecintr_bodygen +isr_vec4: + _vecintr_plain_save 4, 0 + _vecintr_bodygen +isr_vec5: + _vecintr_plain_save 5, 0 + _vecintr_bodygen +isr_vec6: + _vecintr_plain_save 6, 0 + _vecintr_bodygen +isr_vec7: + _vecintr_plain_save 7, 0 + _vecintr_bodygen +isr_vec8: + _vecintr_errorcode_present_save 8 + _vecintr_bodygen +isr_vec10: + _vecintr_errorcode_present_save 10 + _vecintr_bodygen +isr_vec11: + _vecintr_errorcode_present_save 11 + _vecintr_bodygen +isr_vec12: + _vecintr_errorcode_present_save 12 + _vecintr_bodygen +isr_vec13: + _vecintr_errorcode_present_save 13 + _vecintr_bodygen +isr_vec14: + _vecintr_errorcode_present_save 14 + _vecintr_bodygen +isr_vec16: + _vecintr_plain_save 16, 0 + _vecintr_bodygen +isr_vec17: + _vecintr_errorcode_present_save 17 + _vecintr_bodygen +isr_vec18: + _vecintr_plain_save 18, 0 + _vecintr_bodygen +isr_vec19: + _vecintr_plain_save 19, 0 + _vecintr_bodygen +isr_vec20: + _vecintr_plain_save 20, 0 + _vecintr_bodygen +isr_vec21: + _vecintr_errorcode_present_save 21 + _vecintr_bodygen +isr_vec32: + _vecintr_plain_save 32, 0 + _vecintr_bodygen +isr_vec33: + _vecintr_plain_save 33, 0 + _vecintr_bodygen +isr_vec39: + _vecintr_plain_save 39, 0 + _vecintr_bodygen diff --git a/kernel/kmain.c b/kernel/kmain.c index c9ffa8a..8623486 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -69,5 +69,7 @@ void kmain(void) { kprintf(BANNER_TEXT "\n"); + *((int *)0xdeadbeef) = 123; + hal_hang(); }