From 67b5d6ea184c432b21b3f07649ec3ba150a1d350 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Wed, 17 Mar 2021 15:20:53 +0200 Subject: cpuid: show manufacturer and model --- libk/stdlib.h | 6 ++++ libk/string.h | 13 +++++--- src/cpu/cpu.cc | 35 ++++++++++++++++++++ src/cpu/cpu.h | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/kernel.cc | 6 ++++ src/makefile | 1 + 6 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/cpu/cpu.cc create mode 100644 src/cpu/cpu.h diff --git a/libk/stdlib.h b/libk/stdlib.h index 843cc14..0fd1ad8 100644 --- a/libk/stdlib.h +++ b/libk/stdlib.h @@ -62,3 +62,9 @@ void printk(const T& a, const Args&... x) { } extern "C" __attribute__((__noreturn__)) void abort(); + +#define runtime_assert(x, msg) \ + if (!x) { \ + printk(__FILE__, ':', __LINE__, ' ', msg); \ + abort(); \ + } diff --git a/libk/string.h b/libk/string.h index 30824b8..d0a0b32 100644 --- a/libk/string.h +++ b/libk/string.h @@ -1,14 +1,20 @@ #pragma once #include +extern "C" { +void* memcpy(void* dstptr, const void* srcptr, const size_t n); +void* memset(void* bufptr, const int value, const size_t n); +void* memmove(void* dstptr, const void* srcptr, const size_t n); +int memcmp(const void* aptr, const void* bptr, const size_t n); +} + /** * Calculate the length of the string (in bytes) pointed to by str, excluding * the terminating null character. */ constexpr size_t strlen(const char* str) { size_t len = 0; - while (str[len] != '\0') - ++len; + while (str[len] != '\0') ++len; return len; } @@ -32,8 +38,7 @@ public: operator bool() const { return reverse ? (pos >= 0) : (pos < length); } explicit ViewIterator(const char* b, size_t l, bool r = false) : buffer(b), length(l), reverse(r) { - if (reverse) - pos = length - 1; + if (reverse) pos = length - 1; }; private: diff --git a/src/cpu/cpu.cc b/src/cpu/cpu.cc new file mode 100644 index 0000000..0c9403f --- /dev/null +++ b/src/cpu/cpu.cc @@ -0,0 +1,35 @@ +#include "cpu.h" +#include + +static_assert(sizeof(CPU::features_t) == 2 * sizeof(uint32_t)); + +CPU::CPU() { + static_assert(sizeof(CPU::version_t) == sizeof(uint32_t)); + struct { + uint32_t d; + uint32_t c; + uint32_t b; + uint32_t a; + } __attribute__((packed)) r; + size_t highest_param = 0; + + for (int i = 0; i <= highest_param; ++i) { + asm volatile("cpuid" : "=a"(r.a), "=b"(r.b), "=c"(r.c), "=d"(r.d) : "a"(i)); + + switch (i) { + case 0: + highest_param = static_cast(r.a); + memcpy(&m_manufacturer[0], &r.b, sizeof(r.b)); + memcpy(&m_manufacturer[4], &r.d, sizeof(r.d)); + memcpy(&m_manufacturer[8], &r.c, sizeof(r.c)); + break; + case 1: + memcpy(&m_info, &r.a, sizeof(r.a)); + memcpy(&m_features, &r.d, sizeof(CPU::features_t)); + break; + default: + return; + } + } + +} diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h new file mode 100644 index 0000000..2dc9cbe --- /dev/null +++ b/src/cpu/cpu.h @@ -0,0 +1,101 @@ +#pragma once + +#include + +class CPU { +public: + struct features_t { + bool fpu : 1 = false; // onboard x87 fpu + bool vme : 1 = false; // virtual 8086 mode + bool de : 1 = false; // debugging extensions + bool pse : 1 = false; // page size extension + bool tsc : 1 = false; // time stamp counter + bool msr : 1 = false; // model specific registers + bool pae : 1 = false; // physical address extension + bool mce : 1 = false; // machine check exception + bool cx8 : 1 = false; // compare and swap instruction + bool apic : 1 = false; // onboard apic + bool __r0 : 1 = false; + bool sep : 1 = false; // sysenter and sysexit + bool mtrr : 1 = false; // memory type range registers + bool pge : 1 = false; // page global enable bit + bool mca : 1 = false; // machine check architecture + bool cmov : 1 = false; // conditional move + bool pat : 1 = false; // page attribute table + bool pse36 : 1 = false; // 36-bit page size extension + bool psn : 1 = false; // processor serial number + bool clfsh : 1 = false; // clflish + bool __r1 : 1 = false; + bool ds : 1 = false; // debug store + bool acpi : 1 = false; // onboard thermal control for acpi + bool mmx : 1 = false; // mmx extension + bool fxsr : 1 = false; // fxsave, fxrestor + bool sse : 1 = false; // sse extension + bool sse2 : 1 = false; // sse2 extension + bool ss : 1 = false; // cpu cache implements self-snoop + bool htt : 1 = false; // hyper-threading + bool tm : 1 = false; // thermal monitor auto-limits temperature + bool ia64 : 1 = false; // ia64 processor emulating x86 + bool pbe : 1 = false; // pending break enable + + bool sse3 : 1 = false; // sse3 extension + bool pclmulqdq : 1 = false; // pclmulqdq + bool dtes64 : 1 = false; // 64-bit debug store + bool monitor : 1 = false; // monitor and mwait instructions (sse3) + bool ds_cpl : 1 = false; // CPL qualified debug store + bool vmx : 1 = false; // virtual machine extensions + bool smx : 1 = false; // safer mode extensions + bool est : 1 = false; // enahnced speedstep + bool tm2 : 1 = false; // thermal monitor 2 + bool ssse3 : 1 = false; // supplemental sse3 + bool cnxt_id : 1 = false; // L1 context ID + bool sdbg : 1 = false; // Silicon Debug interface + bool fma : 1 = false; // fused multiply-add + bool cx16 : 1 = false; // cmpxchg16b instruction + bool xtpr : 1 = false; // can disable sending task priority messages + bool pdcm : 1 = false; // perfom and debug capability + bool __r2 : 1 = false; + bool pcid : 1 = false; // process context identifiers + bool dca : 1 = false; // direct cache access for DMA writes + bool sse41 : 1 = false; // sse 4.1 + bool sse42 : 1 = false; // sse 4.2 + bool x2apic : 1 = false; // x2APIX + bool movbe : 1 = false; // movbe instruction + bool popcnt : 1 = false; // popcnt instruction + bool tsc_deadline : 1 = false; // apic implements one-shot operation using tsc deadline + bool aes : 1 = false; // aes instruction set + bool xsave : 1 = false; // xsave, xrestor, xsetbv, xgetbv + bool oxsave : 1 = false; // xsave enabled by OS + bool avx : 1 = false; // advanced vector extensions + bool f16c : 1 = false; // f16c fp feature + bool rdrnd : 1 = false; // rdrand + bool hypervisor : 1 = false; // hypervisor present + } __attribute__((packed)); + + CPU(); + ~CPU() = default; + + const char* manufacturer() const { return m_manufacturer; } + uint8_t family() const { return m_info.family == 15 ? m_info.family + m_info.family_ex : m_info.family; } + uint8_t model() const { + return (m_info.model == 6 || m_info.model == 15) ? (static_cast(m_info.model_ex << 4) + m_info.model) + : m_info.model; + } + uint8_t stepping() const { return m_info.stepping; } + auto features() const { return m_features; } + +private: + char m_manufacturer[13] = {'\0'}; + struct version_t { + uint8_t stepping : 4 = 0; + uint8_t model : 4 = 0; + uint8_t family : 4 = 0; + uint8_t type : 2 = 0; + uint8_t reserved_1 : 2 = 0; + uint8_t model_ex : 4 = 0; + uint8_t family_ex : 8 = 0; + uint8_t reserved_2 : 4 = 0; + } __attribute__((packed)) m_info; + + features_t m_features; +}; diff --git a/src/kernel.cc b/src/kernel.cc index 0d8874c..3110419 100644 --- a/src/kernel.cc +++ b/src/kernel.cc @@ -11,6 +11,7 @@ #include #include #include "cga.h" +#include "cpu/cpu.h" #include "gdt.h" #include "idt.h" #include "keyboard.h" @@ -41,6 +42,11 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m #endif printk("Hello, kernel World!\n"); + CPU core0; + printk("cpuid: ", core0.manufacturer(), " family ", core0.family(), " model ", core0.model(), " stepping ", + core0.stepping(), '\n'); + runtime_assert(core0.features().fpu, "CPU lacks fpu"); + runtime_assert(core0.features().cx8, "CPU lacks cx8"); dump_address(); // dump_gdt(); diff --git a/src/makefile b/src/makefile index d3b3c47..68ec6d6 100644 --- a/src/makefile +++ b/src/makefile @@ -3,6 +3,7 @@ AS_OBJ += src/boot.o \ CXX_OBJ += src/kernel.o \ src/kernel/dump_gdt.o src/kernel/dump_multiboot.o \ + src/cpu/cpu.o \ src/gdt.o \ src/gdt/segmentdescriptor.o \ src/idt.o \ -- cgit v1.2.1