summaryrefslogtreecommitdiff
path: root/kernel/cpu
diff options
context:
space:
mode:
authorIan McFarlane <i.mcfarlane2002@gmail.com>2025-04-17 14:19:40 -0400
committerIan McFarlane <i.mcfarlane2002@gmail.com>2025-04-17 14:19:40 -0400
commit7108e7c951f7cff79ce4992f1c7d8d0af0bb5af6 (patch)
treee99684b87952bded5e51c83848a5d35ab53d9ab0 /kernel/cpu
parentstarting on ata (diff)
parentclang 18 in flake instead of zig (diff)
downloadcomus-7108e7c951f7cff79ce4992f1c7d8d0af0bb5af6.tar.gz
comus-7108e7c951f7cff79ce4992f1c7d8d0af0bb5af6.tar.bz2
comus-7108e7c951f7cff79ce4992f1c7d8d0af0bb5af6.zip
Merge branch 'main' into ata
Diffstat (limited to '')
-rw-r--r--kernel/cpu/cpu.c230
-rw-r--r--kernel/cpu/fpu.c13
-rw-r--r--kernel/cpu/fpu.h14
-rw-r--r--kernel/cpu/idt.c67
4 files changed, 231 insertions, 93 deletions
diff --git a/kernel/cpu/cpu.c b/kernel/cpu/cpu.c
index a77baac..136a1d8 100644
--- a/kernel/cpu/cpu.c
+++ b/kernel/cpu/cpu.c
@@ -1,11 +1,237 @@
+#include <lib.h>
+#include <comus/cpu.h>
-#include "fpu.h"
#include "pic.h"
#include "idt.h"
+static inline 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));
+}
+
+static inline void sse_init(void)
+{
+ size_t cr0, cr4;
+ __asm__ volatile("mov %%cr0, %0" : "=r"(cr0));
+ cr0 &= ~0x4; // clear coprocessor emulation
+ cr0 |= 0x2; // set coprocessor monitoring
+ __asm__ volatile("mov %0, %%cr0" ::"r"(cr0));
+ __asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
+ cr4 |= 1 << 9; // set CR4.OSFXSR
+ cr4 |= 1 << 10; // set CR4.OSXMMEXCPT
+ __asm__ volatile("mov %0, %%cr4" ::"r"(cr4));
+}
+
+static inline void fxsave_init(void)
+{
+ static char fxsave_region[512] __attribute__((aligned(16)));
+ __asm__ volatile("fxsave %0" ::"m"(fxsave_region));
+}
+
+static inline void xsave_init(void)
+{
+ size_t cr4;
+ __asm__ volatile("mov %%cr4, %0" : "=r"(cr4));
+ cr4 |= 1 << 18; // set CR4.OSXSAVE
+ __asm__ volatile("mov %0, %%cr4" ::"r"(cr4));
+}
+
+static inline void avx_init(void)
+{
+ __asm__ volatile("pushq %rax;"
+ "pushq %rcx;"
+ "pushq %rdx;"
+ "xorq %rcx, %rcx;"
+ "xgetbv;"
+ "orq $7, %rax;"
+ "xsetbv;"
+ "popq %rdx;"
+ "popq %rcx;"
+ "popq %rax;");
+}
+
void cpu_init(void)
{
+ struct cpu_feat feats;
+ cpu_feats(&feats);
+
pic_remap();
idt_init();
- fpu_init();
+ if (feats.fpu)
+ fpu_init();
+ if (feats.sse) {
+ sse_init();
+ fxsave_init();
+ }
+ if (feats.xsave) {
+ xsave_init();
+ if (feats.avx)
+ avx_init();
+ }
+}
+
+void cpu_report(void)
+{
+ char vendor[12], name[48];
+ struct cpu_feat feats;
+
+ cpu_name(name);
+ cpu_vendor(vendor);
+ cpu_feats(&feats);
+
+ kprintf("CPU\n");
+ kprintf("Name: %.*s\n", 48, name);
+ kprintf("Vendor: %.*s\n", 12, vendor);
+ kputs("Features:");
+ if (feats.fpu)
+ kputs(" FPU");
+ if (feats.mmx)
+ kputs(" MMX");
+ if (feats.sse)
+ kputs(" SSE");
+ if (feats.sse2)
+ kputs(" SSE2");
+ if (feats.sse3)
+ kputs(" SSE3");
+ if (feats.ssse3)
+ kputs(" SSSE3");
+ if (feats.sse41)
+ kputs(" SSE4.1");
+ if (feats.sse42)
+ kputs(" SSE4.2");
+ if (feats.sse4a)
+ kputs(" SSE4a");
+ if (feats.avx)
+ kputs(" AVX");
+ if (feats.xsave)
+ kputs(" XSAVE");
+ if (feats.avx2)
+ kputs(" AVX2");
+ if (feats.avx512)
+ kputs(" AVX-512");
+ kputs("\n\n");
+}
+
+static inline void cpuid(uint32_t leaf, uint32_t *eax, uint32_t *ebx,
+ uint32_t *ecx, uint32_t *edx)
+{
+ __asm__ volatile("cpuid"
+ : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
+ : "0"(leaf));
+}
+
+static inline void cpuid_count(uint32_t leaf, uint32_t subleaf, uint32_t *eax,
+ uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+ __asm__ volatile("cpuid"
+ : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
+ : "0"(leaf), "2"(subleaf));
+}
+
+void cpu_vendor(char vendor[12])
+{
+ uint32_t ignore;
+ cpuid(0, &ignore, (uint32_t *)(vendor + 0), (uint32_t *)(vendor + 8),
+ (uint32_t *)(vendor + 4));
+}
+
+void cpu_name(char name[48])
+{
+ cpuid(0x80000002, (uint32_t *)(name + 0), (uint32_t *)(name + 4),
+ (uint32_t *)(name + 8), (uint32_t *)(name + 12));
+ cpuid(0x80000003, (uint32_t *)(name + 16), (uint32_t *)(name + 20),
+ (uint32_t *)(name + 24), (uint32_t *)(name + 28));
+ cpuid(0x80000004, (uint32_t *)(name + 32), (uint32_t *)(name + 36),
+ (uint32_t *)(name + 40), (uint32_t *)(name + 44));
+}
+
+void cpu_feats(struct cpu_feat *feats)
+{
+ memset(feats, 0, sizeof(struct cpu_feat));
+
+ uint32_t ignore;
+ uint32_t ecx_1, edx_1;
+ uint32_t ebx_7;
+
+ cpuid(1, &ignore, &ignore, &ecx_1, &edx_1);
+ cpuid_count(7, 0, &ignore, &ebx_7, &ignore, &ignore);
+
+ feats->fpu = edx_1 & (1 << 0) ? 1 : 0;
+ feats->mmx = edx_1 & (1 << 23) ? 1 : 0;
+ feats->sse = edx_1 & (1 << 25) ? 1 : 0;
+ feats->sse2 = edx_1 & (1 << 26) ? 1 : 0;
+ feats->sse3 = ecx_1 & (1 << 0) ? 1 : 0;
+ feats->ssse3 = ecx_1 & (1 << 9) ? 1 : 0;
+ feats->sse41 = ecx_1 & (1 << 19) ? 1 : 0;
+ feats->sse42 = ecx_1 & (1 << 20) ? 1 : 0;
+ feats->sse4a = ecx_1 & (1 << 6) ? 1 : 0;
+ feats->avx = ecx_1 & (1 << 28) ? 1 : 0;
+ feats->xsave = ecx_1 & (1 << 26) ? 1 : 0;
+ feats->avx2 = ebx_7 & (1 << 5) ? 1 : 0;
+ feats->avx512 = ebx_7 & (7 << 16) ? 1 : 0;
+}
+
+void cpu_print_regs(struct cpu_regs *regs)
+{
+ kprintf("rax: %#016lx (%lu)\n", regs->rax, regs->rax);
+ kprintf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx);
+ kprintf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx);
+ kprintf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx);
+ kprintf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi);
+ kprintf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi);
+ kprintf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp);
+ kprintf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp);
+ kprintf("r8 : %#016lx (%lu)\n", regs->r8, regs->r8);
+ kprintf("r9 : %#016lx (%lu)\n", regs->r9, regs->r9);
+ kprintf("r10: %#016lx (%lu)\n", regs->r10, regs->r10);
+ kprintf("r11: %#016lx (%lu)\n", regs->r11, regs->r11);
+ kprintf("r12: %#016lx (%lu)\n", regs->r12, regs->r12);
+ kprintf("r13: %#016lx (%lu)\n", regs->r13, regs->r13);
+ kprintf("r14: %#016lx (%lu)\n", regs->r14, regs->r14);
+ kprintf("r15: %#016lx (%lu)\n", regs->r15, regs->r15);
+ kprintf("rip: %#016lx (%lu)\n", regs->rip, regs->rip);
+ kprintf("rflags: %#016lx (%lu)\n", regs->rflags, regs->rflags);
+ kputs("rflags: ");
+ if (regs->rflags & (1 << 0))
+ kputs("CF ");
+ if (regs->rflags & (1 << 2))
+ kputs("PF ");
+ if (regs->rflags & (1 << 4))
+ kputs("AF ");
+ if (regs->rflags & (1 << 6))
+ kputs("ZF ");
+ if (regs->rflags & (1 << 7))
+ kputs("SF ");
+ if (regs->rflags & (1 << 8))
+ kputs("TF ");
+ if (regs->rflags & (1 << 9))
+ kputs("IF ");
+ if (regs->rflags & (1 << 10))
+ kputs("DF ");
+ if (regs->rflags & (1 << 11))
+ kputs("OF ");
+ if (regs->rflags & (3 << 12))
+ kputs("IOPL ");
+ if (regs->rflags & (1 << 14))
+ kputs("NT ");
+ if (regs->rflags & (1 << 15))
+ kputs("MD ");
+ if (regs->rflags & (1 << 16))
+ kputs("RF ");
+ if (regs->rflags & (1 << 17))
+ kputs("VM ");
+ if (regs->rflags & (1 << 18))
+ kputs("AC ");
+ if (regs->rflags & (1 << 19))
+ kputs("VIF ");
+ if (regs->rflags & (1 << 20))
+ kputs("VIP ");
+ if (regs->rflags & (1 << 21))
+ kputs("ID ");
+ kputs("\n");
}
diff --git a/kernel/cpu/fpu.c b/kernel/cpu/fpu.c
deleted file mode 100644
index cafe6e5..0000000
--- a/kernel/cpu/fpu.c
+++ /dev/null
@@ -1,13 +0,0 @@
-#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
deleted file mode 100644
index edb4e81..0000000
--- a/kernel/cpu/fpu.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * @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.c b/kernel/cpu/idt.c
index 5b93987..8b4465f 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -1,4 +1,3 @@
-#include "lib/klib.h"
#include <lib.h>
#include <comus/memory.h>
#include <comus/asm.h>
@@ -71,67 +70,6 @@ void idt_init(void)
__asm__ volatile("lidt %0" : : "m"(idtr));
}
-static void isr_print_regs(regs_t *regs)
-{
- kprintf("rax: %#016lx (%lu)\n", regs->rax, regs->rax);
- kprintf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx);
- kprintf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx);
- kprintf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx);
- kprintf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi);
- kprintf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi);
- kprintf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp);
- kprintf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp);
- kprintf("r8 : %#016lx (%lu)\n", regs->r8, regs->r8);
- kprintf("r9 : %#016lx (%lu)\n", regs->r9, regs->r9);
- kprintf("r10: %#016lx (%lu)\n", regs->r10, regs->r10);
- kprintf("r11: %#016lx (%lu)\n", regs->r11, regs->r11);
- kprintf("r12: %#016lx (%lu)\n", regs->r12, regs->r12);
- kprintf("r13: %#016lx (%lu)\n", regs->r13, regs->r13);
- kprintf("r14: %#016lx (%lu)\n", regs->r14, regs->r14);
- kprintf("r15: %#016lx (%lu)\n", regs->r15, regs->r15);
- kprintf("rip: %#016lx (%lu)\n", regs->rip, regs->rip);
- kprintf("rflags: %#016lx (%lu)\n", (uint64_t)regs->rflags.raw,
- (uint64_t)regs->rflags.raw);
- kputs("rflags: ");
- if (regs->rflags.cf)
- kputs("CF ");
- if (regs->rflags.pf)
- kputs("PF ");
- if (regs->rflags.af)
- kputs("AF ");
- if (regs->rflags.zf)
- kputs("ZF ");
- if (regs->rflags.sf)
- kputs("SF ");
- if (regs->rflags.tf)
- kputs("TF ");
- if (regs->rflags.if_)
- kputs("IF ");
- if (regs->rflags.df)
- kputs("DF ");
- if (regs->rflags.of)
- kputs("OF ");
- if (regs->rflags.iopl)
- kputs("IOPL ");
- if (regs->rflags.nt)
- kputs("NT ");
- if (regs->rflags.md)
- kputs("MD ");
- if (regs->rflags.rf)
- kputs("RF ");
- if (regs->rflags.vm)
- kputs("VM ");
- if (regs->rflags.ac)
- kputs("AC ");
- if (regs->rflags.vif)
- kputs("VIF ");
- if (regs->rflags.vip)
- kputs("VIP ");
- if (regs->rflags.id)
- kputs("ID ");
- kputs("\n");
-}
-
#define EX_DEBUG 0x01
#define EX_BREAKPOINT 0x03
#define EX_PAGE_FAULT 0x0e
@@ -172,7 +110,8 @@ char *EXCEPTIONS[] = {
"Reserved",
};
-void idt_exception_handler(uint64_t exception, uint64_t code, regs_t *state)
+void idt_exception_handler(uint64_t exception, uint64_t code,
+ struct cpu_regs *state)
{
uint64_t cr2;
@@ -194,7 +133,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code, regs_t *state)
kputs("\n");
- isr_print_regs(state);
+ cpu_print_regs(state);
kputs("\n");