From 16b7b4c2c008c976ee5948c97a8337d6224c3be9 Mon Sep 17 00:00:00 2001 From: Freya Murphy <freya@freyacat.org> Date: Thu, 3 Apr 2025 21:32:00 -0400 Subject: [PATCH] add 64-bit idt/pic and fix paging --- build.zig | 7 +- kernel/cpu/cpu.c | 10 + kernel/cpu/fpu.c | 12 + kernel/cpu/fpu.h | 14 + kernel/cpu/idt.S | 666 +++++++++++++++++++++++++++++++++++++ kernel/cpu/idt.c | 204 ++++++++++++ kernel/cpu/idt.h | 68 ++++ kernel/cpu/pic.c | 90 +++++ kernel/cpu/pic.h | 42 +++ kernel/include/comus/cpu.h | 17 + kernel/io/io.c | 11 +- kernel/kernel.c | 10 +- kernel/kernel.ld | 8 - kernel/memory/paging.c | 2 +- kernel/memory/virtalloc.c | 2 +- 15 files changed, 1147 insertions(+), 16 deletions(-) create mode 100644 kernel/cpu/cpu.c create mode 100644 kernel/cpu/fpu.c create mode 100644 kernel/cpu/fpu.h create mode 100644 kernel/cpu/idt.S create mode 100644 kernel/cpu/idt.c create mode 100644 kernel/cpu/idt.h create mode 100644 kernel/cpu/pic.c create mode 100644 kernel/cpu/pic.h create mode 100644 kernel/include/comus/cpu.h diff --git a/build.zig b/build.zig index f7e0e87..6ca2ff3 100644 --- a/build.zig +++ b/build.zig @@ -24,7 +24,12 @@ const boot_src = &[_][]const u8{"boot/boot.S"}; const kernel_src = &[_][]const u8{ "kernel/entry.S", // must be first - "kernel/kernel.c", + "kernel/kernel.c", // main function + "kernel/cpu/cpu.c", + "kernel/cpu/fpu.c", + "kernel/cpu/idt.c", + "kernel/cpu/idt.S", + "kernel/cpu/pic.c", "kernel/io/io.c", "kernel/io/panic.c", "kernel/memory/memory.c", diff --git a/kernel/cpu/cpu.c b/kernel/cpu/cpu.c new file mode 100644 index 0000000..8f37402 --- /dev/null +++ b/kernel/cpu/cpu.c @@ -0,0 +1,10 @@ + +#include "fpu.h" +#include "pic.h" +#include "idt.h" + +void cpu_init(void) { + pic_remap(); + idt_init(); + fpu_init(); +} diff --git a/kernel/cpu/fpu.c b/kernel/cpu/fpu.c new file mode 100644 index 0000000..f2674a7 --- /dev/null +++ b/kernel/cpu/fpu.c @@ -0,0 +1,12 @@ +#include <lib.h> + +#include "fpu.h" + +void fpu_init(void) { + size_t cr4; + uint16_t cw = 0x37F; + __asm__ volatile ("mov %%cr4, %0" : "=r"(cr4)); + cr4 |= 0x200; + __asm__ volatile ("mov %0, %%cr4" :: "r"(cr4)); + __asm__ volatile("fldcw %0" :: "m"(cw)); +} diff --git a/kernel/cpu/fpu.h b/kernel/cpu/fpu.h new file mode 100644 index 0000000..edb4e81 --- /dev/null +++ b/kernel/cpu/fpu.h @@ -0,0 +1,14 @@ +/** + * @file fpu.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * FPU functions + */ + +#ifndef FPU_H_ +#define FPU_H_ + +void fpu_init(void); + +#endif /* fpu.h */ diff --git a/kernel/cpu/idt.S b/kernel/cpu/idt.S new file mode 100644 index 0000000..0ba35f8 --- /dev/null +++ b/kernel/cpu/idt.S @@ -0,0 +1,666 @@ + .global isr_stub_table + + .extern idt_exception_handler + .extern idt_pic_timer + .extern idt_pic_keyboard + .extern idt_pic_mouse + .extern idt_pic_eoi + +.macro PUSHALL + pushq %rax + pushq %rbx + pushq %rcx + pushq %rdx + pushq %rsi + pushq %rdi + pushq %rbp + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 +.endm + +.macro POPALL + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rbp + popq %rdi + popq %rsi + popq %rdx + popq %rcx + popq %rbx + popq %rax +.endm + +# call the exception handler with the interrupt number +# args: interrupt number +.macro ISRException num + .align 8 +isr_stub_\num: + PUSHALL + cld + movq $\num, %rdi # exception number + movq $0, %rsi # placeholder error code + movq %rsp, %rdx # top of stack + callq idt_exception_handler + POPALL + iretq +.endm + +# call the exception handler with the interrupt number +# these exceptions also put an error code on the stack +# args: interrupt number +.macro ISRExceptionCode num + .align 8 +isr_stub_\num: + # retrieve the error code without corrupting registers + mov %eax, isr_tmp + popq %rax + mov %eax, isr_err_code + movq isr_tmp, %rax + PUSHALL + cld + movq $\num, %rdi # exception number + movq isr_err_code, %rsi # error code + movq %rsp, %rdx # top of stack + callq idt_exception_handler + POPALL + iretq +.endm + +.macro PICGeneric num + .align 8 +isr_stub_\num: + PUSHALL + cld + movq $\num, %rdi + callq idt_pic_eoi + POPALL + iretq +.endm + +.macro PICTimer num + .align 8 +isr_stub_\num: + PUSHALL + cld + callq idt_pic_timer + movq $\num, %rdi + callq idt_pic_eoi + POPALL + iretq +.endm + +.macro PICKeyboard num + .align 8 +isr_stub_\num: + PUSHALL + cld + callq idt_pic_keyboard + movq $\num, %rdi + callq idt_pic_eoi + POPALL + iretq +.endm + +.macro PICMouse num + .align 8 +isr_stub_\num: + PUSHALL + cld + callq idt_pic_mouse + movq $\num, %rdi + callq idt_pic_eoi + POPALL + iretq +.endm + +# do nothing +# args: interrupt number +.macro ISRIgnore num + .align 8 +isr_stub_\num: + iretq +.endm + +# isr temp storage + .section .data +isr_tmp: + .quad 0 +isr_err_code: + .quad 0 + +# isr stub table + .section .rodata + .align 16 + .code64 +isr_stub_table: + .quad isr_stub_0 + .quad isr_stub_1 + .quad isr_stub_2 + .quad isr_stub_3 + .quad isr_stub_4 + .quad isr_stub_5 + .quad isr_stub_6 + .quad isr_stub_7 + .quad isr_stub_8 + .quad isr_stub_9 + .quad isr_stub_10 + .quad isr_stub_11 + .quad isr_stub_12 + .quad isr_stub_13 + .quad isr_stub_14 + .quad isr_stub_15 + .quad isr_stub_16 + .quad isr_stub_17 + .quad isr_stub_18 + .quad isr_stub_19 + .quad isr_stub_20 + .quad isr_stub_21 + .quad isr_stub_22 + .quad isr_stub_23 + .quad isr_stub_24 + .quad isr_stub_25 + .quad isr_stub_26 + .quad isr_stub_27 + .quad isr_stub_28 + .quad isr_stub_29 + .quad isr_stub_30 + .quad isr_stub_31 + .quad isr_stub_32 + .quad isr_stub_33 + .quad isr_stub_34 + .quad isr_stub_35 + .quad isr_stub_36 + .quad isr_stub_37 + .quad isr_stub_38 + .quad isr_stub_39 + .quad isr_stub_40 + .quad isr_stub_41 + .quad isr_stub_42 + .quad isr_stub_43 + .quad isr_stub_44 + .quad isr_stub_45 + .quad isr_stub_46 + .quad isr_stub_47 + .quad isr_stub_48 + .quad isr_stub_49 + .quad isr_stub_50 + .quad isr_stub_51 + .quad isr_stub_52 + .quad isr_stub_53 + .quad isr_stub_54 + .quad isr_stub_55 + .quad isr_stub_56 + .quad isr_stub_57 + .quad isr_stub_58 + .quad isr_stub_59 + .quad isr_stub_60 + .quad isr_stub_61 + .quad isr_stub_62 + .quad isr_stub_63 + .quad isr_stub_64 + .quad isr_stub_65 + .quad isr_stub_66 + .quad isr_stub_67 + .quad isr_stub_68 + .quad isr_stub_69 + .quad isr_stub_70 + .quad isr_stub_71 + .quad isr_stub_72 + .quad isr_stub_73 + .quad isr_stub_74 + .quad isr_stub_75 + .quad isr_stub_76 + .quad isr_stub_77 + .quad isr_stub_78 + .quad isr_stub_79 + .quad isr_stub_80 + .quad isr_stub_81 + .quad isr_stub_82 + .quad isr_stub_83 + .quad isr_stub_84 + .quad isr_stub_85 + .quad isr_stub_86 + .quad isr_stub_87 + .quad isr_stub_88 + .quad isr_stub_89 + .quad isr_stub_90 + .quad isr_stub_91 + .quad isr_stub_92 + .quad isr_stub_93 + .quad isr_stub_94 + .quad isr_stub_95 + .quad isr_stub_96 + .quad isr_stub_97 + .quad isr_stub_98 + .quad isr_stub_99 + .quad isr_stub_100 + .quad isr_stub_101 + .quad isr_stub_102 + .quad isr_stub_103 + .quad isr_stub_104 + .quad isr_stub_105 + .quad isr_stub_106 + .quad isr_stub_107 + .quad isr_stub_108 + .quad isr_stub_109 + .quad isr_stub_110 + .quad isr_stub_111 + .quad isr_stub_112 + .quad isr_stub_113 + .quad isr_stub_114 + .quad isr_stub_115 + .quad isr_stub_116 + .quad isr_stub_117 + .quad isr_stub_118 + .quad isr_stub_119 + .quad isr_stub_120 + .quad isr_stub_121 + .quad isr_stub_122 + .quad isr_stub_123 + .quad isr_stub_124 + .quad isr_stub_125 + .quad isr_stub_126 + .quad isr_stub_127 + .quad isr_stub_128 + .quad isr_stub_129 + .quad isr_stub_130 + .quad isr_stub_131 + .quad isr_stub_132 + .quad isr_stub_133 + .quad isr_stub_134 + .quad isr_stub_135 + .quad isr_stub_136 + .quad isr_stub_137 + .quad isr_stub_138 + .quad isr_stub_139 + .quad isr_stub_140 + .quad isr_stub_141 + .quad isr_stub_142 + .quad isr_stub_143 + .quad isr_stub_144 + .quad isr_stub_145 + .quad isr_stub_146 + .quad isr_stub_147 + .quad isr_stub_148 + .quad isr_stub_149 + .quad isr_stub_150 + .quad isr_stub_151 + .quad isr_stub_152 + .quad isr_stub_153 + .quad isr_stub_154 + .quad isr_stub_155 + .quad isr_stub_156 + .quad isr_stub_157 + .quad isr_stub_158 + .quad isr_stub_159 + .quad isr_stub_160 + .quad isr_stub_161 + .quad isr_stub_162 + .quad isr_stub_163 + .quad isr_stub_164 + .quad isr_stub_165 + .quad isr_stub_166 + .quad isr_stub_167 + .quad isr_stub_168 + .quad isr_stub_169 + .quad isr_stub_170 + .quad isr_stub_171 + .quad isr_stub_172 + .quad isr_stub_173 + .quad isr_stub_174 + .quad isr_stub_175 + .quad isr_stub_176 + .quad isr_stub_177 + .quad isr_stub_178 + .quad isr_stub_179 + .quad isr_stub_180 + .quad isr_stub_181 + .quad isr_stub_182 + .quad isr_stub_183 + .quad isr_stub_184 + .quad isr_stub_185 + .quad isr_stub_186 + .quad isr_stub_187 + .quad isr_stub_188 + .quad isr_stub_189 + .quad isr_stub_190 + .quad isr_stub_191 + .quad isr_stub_192 + .quad isr_stub_193 + .quad isr_stub_194 + .quad isr_stub_195 + .quad isr_stub_196 + .quad isr_stub_197 + .quad isr_stub_198 + .quad isr_stub_199 + .quad isr_stub_200 + .quad isr_stub_201 + .quad isr_stub_202 + .quad isr_stub_203 + .quad isr_stub_204 + .quad isr_stub_205 + .quad isr_stub_206 + .quad isr_stub_207 + .quad isr_stub_208 + .quad isr_stub_209 + .quad isr_stub_210 + .quad isr_stub_211 + .quad isr_stub_212 + .quad isr_stub_213 + .quad isr_stub_214 + .quad isr_stub_215 + .quad isr_stub_216 + .quad isr_stub_217 + .quad isr_stub_218 + .quad isr_stub_219 + .quad isr_stub_220 + .quad isr_stub_221 + .quad isr_stub_222 + .quad isr_stub_223 + .quad isr_stub_224 + .quad isr_stub_225 + .quad isr_stub_226 + .quad isr_stub_227 + .quad isr_stub_228 + .quad isr_stub_229 + .quad isr_stub_230 + .quad isr_stub_231 + .quad isr_stub_232 + .quad isr_stub_233 + .quad isr_stub_234 + .quad isr_stub_235 + .quad isr_stub_236 + .quad isr_stub_237 + .quad isr_stub_238 + .quad isr_stub_239 + .quad isr_stub_240 + .quad isr_stub_241 + .quad isr_stub_242 + .quad isr_stub_243 + .quad isr_stub_244 + .quad isr_stub_245 + .quad isr_stub_246 + .quad isr_stub_247 + .quad isr_stub_248 + .quad isr_stub_249 + .quad isr_stub_250 + .quad isr_stub_251 + .quad isr_stub_252 + .quad isr_stub_253 + .quad isr_stub_254 + .quad isr_stub_255 + +# isr stubs + .section .text + .code64 + +ISRException 0 +ISRException 1 +ISRException 2 +ISRException 3 +ISRException 4 +ISRException 5 +ISRException 6 +ISRException 7 +ISRExceptionCode 8 +ISRException 9 +ISRExceptionCode 10 +ISRExceptionCode 11 +ISRExceptionCode 12 +ISRExceptionCode 13 +ISRExceptionCode 14 +ISRException 15 +ISRException 16 +ISRExceptionCode 17 +ISRException 18 +ISRException 19 +ISRException 20 +ISRExceptionCode 21 +ISRException 22 +ISRException 23 +ISRException 24 +ISRException 25 +ISRException 26 +ISRException 27 +ISRException 28 +ISRExceptionCode 29 +ISRExceptionCode 30 +ISRException 31 + +PICTimer 32 # 0 +PICKeyboard 33 # 1 +PICGeneric 34 # 2 +PICGeneric 35 # 3 +PICGeneric 36 # 4 +PICGeneric 37 # 5 +PICGeneric 38 # 6 +PICGeneric 39 # 7 +PICGeneric 40 # 8 +PICGeneric 41 # 9 +PICGeneric 42 # 10 +PICGeneric 43 # 11 +PICMouse 44 # 12 +PICGeneric 45 # 13 +PICGeneric 46 # 14 +PICGeneric 47 # 15 + +ISRIgnore 48 +ISRIgnore 49 +ISRIgnore 50 +ISRIgnore 51 +ISRIgnore 52 +ISRIgnore 53 +ISRIgnore 54 +ISRIgnore 55 +ISRIgnore 56 +ISRIgnore 57 +ISRIgnore 58 +ISRIgnore 59 +ISRIgnore 60 +ISRIgnore 61 +ISRIgnore 62 +ISRIgnore 63 +ISRIgnore 64 +ISRIgnore 65 +ISRIgnore 66 +ISRIgnore 67 +ISRIgnore 68 +ISRIgnore 69 +ISRIgnore 70 +ISRIgnore 71 +ISRIgnore 72 +ISRIgnore 73 +ISRIgnore 74 +ISRIgnore 75 +ISRIgnore 76 +ISRIgnore 77 +ISRIgnore 78 +ISRIgnore 79 +ISRIgnore 80 +ISRIgnore 81 +ISRIgnore 82 +ISRIgnore 83 +ISRIgnore 84 +ISRIgnore 85 +ISRIgnore 86 +ISRIgnore 87 +ISRIgnore 88 +ISRIgnore 89 +ISRIgnore 90 +ISRIgnore 91 +ISRIgnore 92 +ISRIgnore 93 +ISRIgnore 94 +ISRIgnore 95 +ISRIgnore 96 +ISRIgnore 97 +ISRIgnore 98 +ISRIgnore 99 +ISRIgnore 100 +ISRIgnore 101 +ISRIgnore 102 +ISRIgnore 103 +ISRIgnore 104 +ISRIgnore 105 +ISRIgnore 106 +ISRIgnore 107 +ISRIgnore 108 +ISRIgnore 109 +ISRIgnore 110 +ISRIgnore 111 +ISRIgnore 112 +ISRIgnore 113 +ISRIgnore 114 +ISRIgnore 115 +ISRIgnore 116 +ISRIgnore 117 +ISRIgnore 118 +ISRIgnore 119 +ISRIgnore 120 +ISRIgnore 121 +ISRIgnore 122 +ISRIgnore 123 +ISRIgnore 124 +ISRIgnore 125 +ISRIgnore 126 +ISRIgnore 127 +ISRIgnore 128 +ISRIgnore 129 +ISRIgnore 130 +ISRIgnore 131 +ISRIgnore 132 +ISRIgnore 133 +ISRIgnore 134 +ISRIgnore 135 +ISRIgnore 136 +ISRIgnore 137 +ISRIgnore 138 +ISRIgnore 139 +ISRIgnore 140 +ISRIgnore 141 +ISRIgnore 142 +ISRIgnore 143 +ISRIgnore 144 +ISRIgnore 145 +ISRIgnore 146 +ISRIgnore 147 +ISRIgnore 148 +ISRIgnore 149 +ISRIgnore 150 +ISRIgnore 151 +ISRIgnore 152 +ISRIgnore 153 +ISRIgnore 154 +ISRIgnore 155 +ISRIgnore 156 +ISRIgnore 157 +ISRIgnore 158 +ISRIgnore 159 +ISRIgnore 160 +ISRIgnore 161 +ISRIgnore 162 +ISRIgnore 163 +ISRIgnore 164 +ISRIgnore 165 +ISRIgnore 166 +ISRIgnore 167 +ISRIgnore 168 +ISRIgnore 169 +ISRIgnore 170 +ISRIgnore 171 +ISRIgnore 172 +ISRIgnore 173 +ISRIgnore 174 +ISRIgnore 175 +ISRIgnore 176 +ISRIgnore 177 +ISRIgnore 178 +ISRIgnore 179 +ISRIgnore 180 +ISRIgnore 181 +ISRIgnore 182 +ISRIgnore 183 +ISRIgnore 184 +ISRIgnore 185 +ISRIgnore 186 +ISRIgnore 187 +ISRIgnore 188 +ISRIgnore 189 +ISRIgnore 190 +ISRIgnore 191 +ISRIgnore 192 +ISRIgnore 193 +ISRIgnore 194 +ISRIgnore 195 +ISRIgnore 196 +ISRIgnore 197 +ISRIgnore 198 +ISRIgnore 199 +ISRIgnore 200 +ISRIgnore 201 +ISRIgnore 202 +ISRIgnore 203 +ISRIgnore 204 +ISRIgnore 205 +ISRIgnore 206 +ISRIgnore 207 +ISRIgnore 208 +ISRIgnore 209 +ISRIgnore 210 +ISRIgnore 211 +ISRIgnore 212 +ISRIgnore 213 +ISRIgnore 214 +ISRIgnore 215 +ISRIgnore 216 +ISRIgnore 217 +ISRIgnore 218 +ISRIgnore 219 +ISRIgnore 220 +ISRIgnore 221 +ISRIgnore 222 +ISRIgnore 223 +ISRIgnore 224 +ISRIgnore 225 +ISRIgnore 226 +ISRIgnore 227 +ISRIgnore 228 +ISRIgnore 229 +ISRIgnore 230 +ISRIgnore 231 +ISRIgnore 232 +ISRIgnore 233 +ISRIgnore 234 +ISRIgnore 235 +ISRIgnore 236 +ISRIgnore 237 +ISRIgnore 238 +ISRIgnore 239 +ISRIgnore 240 +ISRIgnore 241 +ISRIgnore 242 +ISRIgnore 243 +ISRIgnore 244 +ISRIgnore 245 +ISRIgnore 246 +ISRIgnore 247 +ISRIgnore 248 +ISRIgnore 249 +ISRIgnore 250 +ISRIgnore 251 +ISRIgnore 252 +ISRIgnore 253 +ISRIgnore 254 +ISRIgnore 255 diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c new file mode 100644 index 0000000..af12fff --- /dev/null +++ b/kernel/cpu/idt.c @@ -0,0 +1,204 @@ +#include "stdlib.h" +#include <lib.h> +#include <comus/memory.h> +#include <comus/asm.h> + +#include "idt.h" +#include "pic.h" + +#define IDT_SIZE 256 + +struct idt_entry { + uint16_t isr_low; // low 16 bits of isr + uint16_t kernel_cs; // kernel segment selector + uint8_t ist; // interrupt stack table + uint8_t flags; // gate type, privilege level, present bit + uint16_t isr_mid; // middle 16 bits of isr + uint32_t isr_high; // high 32 bits of isr + uint32_t reserved; +} __attribute__((packed)); + +struct idtr { + uint16_t size; + uint64_t address; +} __attribute__((packed)); + +// interrupt gate +#define GATE_64BIT_INT 0x0E +// trap gate +#define GATE_64BIT_TRAP 0x0F + +// privilege ring allowed to call interrupt +#define RING0 0x00 +#define RING1 0x20 +#define RING2 0x40 +#define RING3 0x60 + +// interrupt is present in IDT +#define PRESENT 0x80 + +__attribute__((aligned(0x10))) +static struct idt_entry idt[256]; + +static struct idtr idtr; +// from idt.S +extern void *isr_stub_table[]; + +// initialize and load the IDT +void idt_init(void) { + // initialize idtr + idtr.address = (uint64_t)&idt; + idtr.size = (uint16_t)sizeof(struct idt_entry) * IDT_SIZE - 1; + + // initialize idt + for (size_t vector = 0; vector < IDT_SIZE; vector++) { + struct idt_entry *entry = &idt[vector]; + + uint64_t isr = (uint64_t)isr_stub_table[vector]; + // interrupts before 0x20 are for cpu exceptions + uint8_t gate_type = (vector < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT; + + entry->kernel_cs = 0x08; // offset of 1 into GDT + entry->ist = 0; + entry->flags = PRESENT | RING0 | gate_type; + entry->isr_low = isr & 0xffff; + entry->isr_mid = (isr >> 16) & 0xffff; + entry->isr_high = (isr >> 32) & 0xffffffff; + entry->reserved = 0; + } + + __asm__ volatile ("lidt %0" : : "m"(idtr)); +} + +static void isr_print_regs(struct isr_regs *regs) { + printf("rax: %#016lx (%lu)\n", regs->rax, regs->rax); + printf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx); + printf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx); + printf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx); + printf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi); + printf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi); + printf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp); + printf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp); + printf("r8 : %#016lx (%lu)\n", regs->r8 , regs->r8 ); + printf("r9 : %#016lx (%lu)\n", regs->r9 , regs->r9 ); + printf("r10: %#016lx (%lu)\n", regs->r10, regs->r10); + printf("r11: %#016lx (%lu)\n", regs->r11, regs->r11); + printf("r12: %#016lx (%lu)\n", regs->r12, regs->r12); + printf("r13: %#016lx (%lu)\n", regs->r13, regs->r13); + printf("r14: %#016lx (%lu)\n", regs->r14, regs->r14); + printf("r15: %#016lx (%lu)\n", regs->r15, regs->r15); + printf("rip: %#016lx (%lu)\n", regs->rip, regs->rip); + printf("rflags: %#016lx (%lu)\n", regs->rflags, regs->rflags); + struct rflags *rflags = (struct rflags *)regs->rflags; + puts("rflags: "); + if (rflags->cf) puts("CF "); + if (rflags->pf) puts("PF "); + if (rflags->af) puts("AF "); + if (rflags->zf) puts("ZF "); + if (rflags->sf) puts("SF "); + if (rflags->tf) puts("TF "); + if (rflags->if_) puts("IF "); + if (rflags->df) puts("DF "); + if (rflags->of) puts("OF "); + if (rflags->iopl) puts("IOPL "); + if (rflags->nt) puts("NT "); + if (rflags->md) puts("MD "); + if (rflags->rf) puts("RF "); + if (rflags->vm) puts("VM "); + if (rflags->ac) puts("AC "); + if (rflags->vif) puts("VIF "); + if (rflags->vip) puts("VIP "); + if (rflags->id) puts("ID "); + puts("\n"); +} + +#define EX_DEBUG 0x01 +#define EX_BREAKPOINT 0x03 +#define EX_PAGE_FAULT 0x0e + +// Intel manual vol 3 ch 6.3.1 +char *EXCEPTIONS[] = { + "Division Error", + "Debug", + "NMI", + "Breakpoint", + "Overflow", + "BOUND Range Exceeded", + "Invalid Opcode", + "Device Not Available", + "Double Fault", + "Coprocessor Segment Overrun", + "Invalid TSS", + "Segment Not Present", + "Stack-Segment Fault", + "General Protection Fault", + "Page Fault", + "Reserved", + "x87 Floating-Point Error", + "Alignment Check", + "Machine Check", + "SIMD Floaing-Point Exception", + "Virtualization Exception", + "Control Protection Exception", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Hypervisor Injection Exception", + "VMM Communication Exception", + "Security Exception", + "Reserved", +}; + +void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) { + uint64_t cr2; + + switch (exception) { + case EX_PAGE_FAULT: + // page faults store the offending address in cr2 + __asm__ volatile ("mov %%cr2, %0" : "=r"(cr2)); + if (!load_page((void *)cr2)) + return; + } + + puts("\n\n!!! EXCEPTION !!!\n"); + printf("%#02lX %s\n", exception, EXCEPTIONS[exception]); + printf("Error code %#lX\n", code); + + if (exception == EX_PAGE_FAULT) { + printf("Page fault address: %#016lx\n", cr2); + } + + puts("\n"); + + isr_print_regs(state); + + puts("\n"); + + while (1) { + halt(); + } +} + +void idt_pic_eoi(uint8_t exception) { + pic_eoi(exception - PIC_REMAP_OFFSET); +} + +int counter = 0; + +void idt_pic_timer(void) { + // print a message once we know the timer works + // but avoid spamming the logs + if (counter == 3) { + //kputs("pic timer!\n"); + } + if (counter <= 3) { + counter++; + } +} + +void idt_pic_keyboard(void) {} + +void idt_pic_mouse(void) {} diff --git a/kernel/cpu/idt.h b/kernel/cpu/idt.h new file mode 100644 index 0000000..46ef4a3 --- /dev/null +++ b/kernel/cpu/idt.h @@ -0,0 +1,68 @@ +/** + * @file idt.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * IDT functions + */ + +#ifndef IDT_H_ +#define IDT_H_ + +#include <stdint.h> + +struct isr_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 rbp; + uint64_t rdi; + uint64_t rsi; + uint64_t rdx; + uint64_t rcx; + uint64_t rbx; + uint64_t rax; + + uint64_t rip; + uint64_t cs; + uint64_t rflags; + uint64_t rsp; + uint64_t ss; +}; + +struct rflags { + uint64_t cf : 1, + : 1, + pf : 1, + : 1, + af : 1, + : 1, + zf : 1, + sf : 1, + + tf : 1, + if_ : 1, + df : 1, + of : 1, + iopl : 2, + nt : 1, + md : 1, + + rf : 1, + vm : 1, + ac : 1, + vif : 1, + vip : 1, + id : 1, + : 42; +}; + +void idt_init(void); + +#endif /* idt.h */ + diff --git a/kernel/cpu/pic.c b/kernel/cpu/pic.c new file mode 100644 index 0000000..7065a03 --- /dev/null +++ b/kernel/cpu/pic.c @@ -0,0 +1,90 @@ +#include <comus/asm.h> + +#include "pic.h" + +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base address for slave PIC */ +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + +#define PIC_EOI 0x20 /* End-of-interrupt command code */ + +#define ICW1_ICW4 0x01 /* Indicates that ICW4 will be present */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +void pic_remap(void) { + uint8_t a1, a2; + + a1 = inb(PIC1_DATA); // save masks + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4); // starts the initialization sequence (in cascade mode) + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, PIC_REMAP_OFFSET); // ICW2: Master PIC vector offset + io_wait(); + outb(PIC2_DATA, PIC_REMAP_OFFSET + 8); // ICW2: Slave PIC vector offset + io_wait(); + outb(PIC1_DATA, 4); // ICW3: tell Master PIC that there is a slave PIC at IRQ2 (0000 0100) + io_wait(); + outb(PIC2_DATA, 2); // ICW3: tell Slave PIC its cascade identity (0000 0010) + io_wait(); + + outb(PIC1_DATA, ICW4_8086); // ICW4: have the PICs use 8086 mode (and not 8080 mode) + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); // restore saved masks. + outb(PIC2_DATA, a2); +} + +void pic_mask(int irq) { + uint16_t port; + uint8_t mask; + if (irq < 8) { + port = PIC1_DATA; + } else { + port = PIC2_DATA; + irq -= 8; + } + mask = inb(port) | (1 << irq); + outb(port, mask); +} + +void pic_unmask(int irq) { + uint16_t port; + uint8_t mask; + if (irq < 8) { + port = PIC1_DATA; + } else { + irq -= 8; + port = PIC2_DATA; + } + mask = inb(port) & ~(1 << irq); + outb(port, mask); +} + +void pic_disable(void) { + outb(PIC1_DATA, 0xff); + outb(PIC2_DATA, 0xff); +} + +void pic_eoi(int irq) { + if (irq >= 8) { + outb(PIC2_COMMAND, PIC_EOI); + } + outb(PIC1_COMMAND, PIC_EOI); +} diff --git a/kernel/cpu/pic.h b/kernel/cpu/pic.h new file mode 100644 index 0000000..0d1aa3a --- /dev/null +++ b/kernel/cpu/pic.h @@ -0,0 +1,42 @@ +/** + * @file pic.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * PIC functions + */ + +#ifndef PIC_H_ +#define PIC_H_ + +#define PIC_REMAP_OFFSET 0x20 + +/** + * Remaps the pie, i.e. initializes it + */ +void pic_remap(void); + +/** + * Masks an external irq to stop firing until un masked + * @param irq - the irq to mask + */ +void pic_mask(int irq); + +/** + * Unmasks an external irq to allow interrupts to continue for that irq + * @param irq - the irq to unmask + */ +void pic_unmask(int irq); + +/** + * Disabled the pick + */ +void pic_disable(void); + +/** + * Tells the pick that the interrupt has ended + * @param irq - the irq that has ended + */ +void pic_eoi(int irq); + +#endif /* pic.h */ diff --git a/kernel/include/comus/cpu.h b/kernel/include/comus/cpu.h new file mode 100644 index 0000000..58fb33d --- /dev/null +++ b/kernel/include/comus/cpu.h @@ -0,0 +1,17 @@ +/** + * @file cpu.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * CPU initalization functions + */ + +#ifndef _CPU_H +#define _CPU_H + +/** + * Initalize current cpu + */ +void cpu_init(void); + +#endif /* cpu.h */ diff --git a/kernel/io/io.c b/kernel/io/io.c index a68114d..11acfdb 100644 --- a/kernel/io/io.c +++ b/kernel/io/io.c @@ -1,9 +1,16 @@ #include <lib.h> #include <stdio.h> +#include <comus/asm.h> + +#define PORT 0x3F8 +static void serial_out(uint8_t ch) { + // wait for output to be free + while ((inb(PORT + 5) & 0x20) == 0); + outb(PORT, ch); +} void fputc(FILE *stream, char c) { (void) stream; - (void) c; - // FIXME: !!! + serial_out(c); } diff --git a/kernel/kernel.c b/kernel/kernel.c index ac0546c..862425a 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,8 +1,12 @@ +#include <comus/cpu.h> #include <comus/memory.h> +#include <lib.h> +#include <stdio.h> void main(void) { - - while (1) - ; + cpu_init(); + memory_init(NULL); + printf("halting...\n"); + while(1); } diff --git a/kernel/kernel.ld b/kernel/kernel.ld index 8ee6a5b..de5971e 100644 --- a/kernel/kernel.ld +++ b/kernel/kernel.ld @@ -6,8 +6,6 @@ SECTIONS kernel_start = .; - . = ALIGN(0x1000); - .boot : { *(.multiboot) } @@ -20,12 +18,6 @@ SECTIONS . = ALIGN(0x1000); - .data : { - *(.data .data.*) - } - - . = ALIGN(0x1000); - .text : { *(.text .stub .text.* .gnu.linkonce.t.*) } diff --git a/kernel/memory/paging.c b/kernel/memory/paging.c index 045afc7..d10cf6d 100644 --- a/kernel/memory/paging.c +++ b/kernel/memory/paging.c @@ -573,7 +573,7 @@ void free_pages(void *virt) unmap_pages(kernel_pml4, virt, pages); } -int kload_page(void *virt_addr) +int load_page(void *virt_addr) { volatile struct pte *page = get_page(kernel_pml4, virt_addr); if (page == NULL) diff --git a/kernel/memory/virtalloc.c b/kernel/memory/virtalloc.c index a9f25af..2b64b72 100644 --- a/kernel/memory/virtalloc.c +++ b/kernel/memory/virtalloc.c @@ -103,7 +103,7 @@ void virtaddr_init(void) .is_alloc = false, .is_used = true, }; - memset(bootstrap_nodes, 0, sizeof(bootstrap_nodes)); + memsetv(bootstrap_nodes, 0, sizeof(bootstrap_nodes)); bootstrap_nodes[0] = init; start_node = &bootstrap_nodes[0]; }