diff --git a/TODO b/TODO index ed93c31..26ca5a2 100644 --- a/TODO +++ b/TODO @@ -14,7 +14,7 @@ Low-Level Hardware & Interrupts [x] IDT [x] Basic IRQs (Internal/Legacy) [x] Proper fault handling (Exceptions, Page Faults, #GP) -[ ] Check for features with CPUID (NX-bit, SSE, AVX) +[-] Check for features with CPUID (NX-bit, SSE, AVX) [ ] APIC driver (Local APIC & I/O APIC) [ ] ACPI driver (Parsing RSDP/MADT for multi-core/APIC) [ ] HPET driver (High precision timing) diff --git a/kernel/include/random.h b/kernel/include/random.h index 4c28955..21fc2c4 100644 --- a/kernel/include/random.h +++ b/kernel/include/random.h @@ -2,7 +2,7 @@ #define _RANDOM_H #include -void rand_init(); +void rand_init(bool rdrand, bool rdseed); extern uint64_t (*get_random_number)(); #endif \ No newline at end of file diff --git a/kernel/include/system.h b/kernel/include/system.h index 344c0be..3fb08b0 100644 --- a/kernel/include/system.h +++ b/kernel/include/system.h @@ -9,6 +9,8 @@ * CPUID */ enum { + CPUID_FEAT_EBX_RDSEED = 1 << 18, + CPUID_FEAT_ECX_SSE3 = 1 << 0, CPUID_FEAT_ECX_PCLMUL = 1 << 1, CPUID_FEAT_ECX_DTES64 = 1 << 2, @@ -87,4 +89,6 @@ void outl(uint16_t port, uint32_t data); void cli(void); void sti(void); +extern uint8_t (*popcountll)(uint64_t num); +void detect_processor_features(); #endif diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index 3024ab5..a401507 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -30,6 +30,9 @@ __noreturn void _start(void) { cpuid(&eax, (void*)&s[0], (void*)&s[8], (void*)&s[4]); pr_info("[kernel] CPUID_GETVENDORID: %s\n", s); + // enable processor extensions + detect_processor_features(); + // System init if ((err = gdt_init()) < 0) panic(NULL, "Failed to initalize GDT. (%d)", err); @@ -43,8 +46,7 @@ __noreturn void _start(void) { if ((err = pag_init()) < 0) panic(NULL, "Failed to initalize Paging. (%d)", err); - // random number generation - rand_init(); + // test random number generation printk("Random number generation test:\n"); for (uint8_t i = 0; i <= 16; i++) { diff --git a/kernel/src/random.c b/kernel/src/random.c index 9e51d33..173e2f6 100644 --- a/kernel/src/random.c +++ b/kernel/src/random.c @@ -25,18 +25,16 @@ uint64_t rand_software() { return LFSR; } -void rand_init() { - uint32_t eax = 1, ebx = 0, ecx = 0, edx = 0; - cpuid(&eax, &ebx, &ecx, &edx); +void rand_init(bool rdrand, bool rdseed) { // check for RDRAND - if ((ecx >> 30) & 1) { + if (rdrand) { get_random_number = rand_rdrand; } else { printk("[\e[33mWARNING\e[0m] RDRAND not available falling back " "to software\n"); // check for RDSEED - if ((ebx >> 18) & 1) { + if (rdseed) { asm(".intel_syntax noprefix\n" "rdseed %0\n" ".att_syntax prefix\n" diff --git a/kernel/src/system.c b/kernel/src/system.c index cdcfd5f..a8af76d 100644 --- a/kernel/src/system.c +++ b/kernel/src/system.c @@ -1,52 +1,93 @@ +#include "types.h" #include +#include #include - void cpuid(uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) { - __asm__ volatile ("cpuid" - : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) - : "a"(*eax) - : "memory"); + __asm__ volatile("cpuid" + : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) + : "a"(*eax) + : "memory"); } -void iowait(void) { - outb(0x80, 0); -} +void iowait(void) { outb(0x80, 0); } uint8_t inb(uint16_t port) { uint8_t r; - __asm__ volatile ("inb %1, %0" : "=a"(r) : "dN"(port)); + __asm__ volatile("inb %1, %0" : "=a"(r) : "dN"(port)); return r; } void outb(uint16_t port, uint8_t data) { - __asm__ volatile ("outb %1, %0" :: "dN"(port), "a"(data)); + __asm__ volatile("outb %1, %0" ::"dN"(port), "a"(data)); } uint16_t inw(uint16_t port) { uint16_t r; - __asm__ volatile ("inw %1, %0" : "=a"(r) : "dN"(port)); + __asm__ volatile("inw %1, %0" : "=a"(r) : "dN"(port)); return r; } void outw(uint16_t port, uint16_t data) { - __asm__ volatile ("outw %1, %0" :: "dN"(port), "a"(data)); + __asm__ volatile("outw %1, %0" ::"dN"(port), "a"(data)); } uint32_t inl(uint16_t port) { uint32_t r; - __asm__ volatile ("inl %1, %0" : "=a"(r) : "dN"(port)); + __asm__ volatile("inl %1, %0" : "=a"(r) : "dN"(port)); return r; } void outl(uint16_t port, uint32_t data) { - __asm__ volatile ("outl %1, %0" :: "dN"(port), "a"(data)); + __asm__ volatile("outl %1, %0" ::"dN"(port), "a"(data)); } -void cli(void) { - __asm__ volatile ("cli"); +void cli(void) { __asm__ volatile("cli"); } + +void sti(void) { __asm__ volatile("sti"); } + +uint8_t (*popcountll)(uint64_t num); + +extern uint8_t popcountll_native(uint64_t num); +asm(".intel_syntax noprefix\n" + ".global popcountll_native\n" + "popcountll_native:" + " popcnt rax, rdi\n" + " ret\n" + ".att_syntax prefix\n"); + +// I have no idea how this works but it is apperently called SWAR +uint8_t popcountll_software(uint64_t num) { + num = num - ((num >> 1) & 0x5555555555555555ULL); + num = (num & 0x3333333333333333ULL) + + ((num >> 2) & 0x3333333333333333ULL); + num = (num + (num >> 4)) & 0x0f0f0f0f0f0f0f0fULL; + return (int)((num * 0x0101010101010101ULL) >> 56); } -void sti(void) { - __asm__ volatile ("sti"); -} +void detect_processor_features() { + // leaf 1 + uint32_t eax = 1, ebx = 0, ecx = 0, edx = 0; + cpuid(&eax, &ebx, &ecx, &edx); + bool rdrand = false; + if (ecx & CPUID_FEAT_ECX_RDRAND) { + rdrand = true; + } + + if (ecx & CPUID_FEAT_ECX_POPCNT) { + popcountll = popcountll_native; + } else { + popcountll = popcountll_software; + } + + // leaf 7 + eax = 7, ebx = 0, ecx = 0, edx = 0; + cpuid(&eax, &ebx, &ecx, &edx); + bool rdseed = false; + if (ebx & CPUID_FEAT_EBX_RDSEED) { + rdseed = true; + } + + // init rng + rand_init(rdrand, rdseed); +}