From 2d4e7cfdeed82023d06f202af6e196b4e37a5342 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sun, 29 Apr 2018 23:50:56 -0700 Subject: [PATCH] Check CPUID info, switch cpu flag to Broadwell --- Makefile | 1 + src/kernel/cpu.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/kernel/cpu.h | 40 ++++++++++++++++++++++++++++ src/kernel/main.cpp | 13 ++++++++++ 4 files changed, 117 insertions(+) create mode 100644 src/kernel/cpu.cpp create mode 100644 src/kernel/cpu.h diff --git a/Makefile b/Makefile index 1ade57a..332d234 100644 --- a/Makefile +++ b/Makefile @@ -116,6 +116,7 @@ QEMUOPTS += -drive file=$(BUILD_D)/fs.img,format=raw QEMUOPTS += -smp $(CPUS) -m 512 QEMUOPTS += -d mmu,guest_errors,int -D popcorn.log QEMUOPTS += -no-reboot +QEMUOPTS += -cpu Broadwell QEMUOPTS += $(QEMUEXTRA) diff --git a/src/kernel/cpu.cpp b/src/kernel/cpu.cpp new file mode 100644 index 0000000..60d0f90 --- /dev/null +++ b/src/kernel/cpu.cpp @@ -0,0 +1,63 @@ +#include +#include "kutil/memory.h" +#include "cpu.h" +#include "log.h" + +inline static void +__cpuid( + uint32_t leaf, + uint32_t subleaf, + uint32_t *eax, + uint32_t *ebx = nullptr, + uint32_t *ecx = nullptr, + uint32_t *edx = nullptr) +{ + uint32_t a, b, c, d; + __asm__ __volatile__ ( "cpuid" + : "=a"(a), "=b"(b), "=c"(c), "=d"(d) + : "a"(leaf), "c"(subleaf) + ); + if (eax) *eax = a; + if (ebx) *ebx = b; + if (ecx) *ecx = c; + if (edx) *edx = d; +} + + +cpu_id::cpu_id() +{ + __cpuid(0, 0, + &m_high_leaf, + reinterpret_cast(&m_vendor_id[0]), + reinterpret_cast(&m_vendor_id[8]), + reinterpret_cast(&m_vendor_id[4])); + + uint32_t eax = 0; + __cpuid(0, 1, &eax); + + m_stepping = eax & 0xf; + m_model = (eax >> 4) & 0xf; + m_family = (eax >> 8) & 0xf; + + m_cpu_type = (eax >> 12) & 0x3; + + uint32_t ext_model = (eax >> 16) & 0xf; + uint32_t ext_family = (eax >> 20) & 0xff; + + if (m_family == 0x6 || m_family == 0xf) + m_model = (ext_model << 4) + m_model; + + if (m_family == 0xf) + m_family += ext_family; + +} + +cpu_id::regs +cpu_id::get(uint32_t leaf, uint32_t sub) const +{ + if (leaf > m_high_leaf) return {}; + + regs ret; + __cpuid(leaf, sub, &ret.eax, &ret.ebx, &ret.ecx, &ret.edx); + return ret; +} diff --git a/src/kernel/cpu.h b/src/kernel/cpu.h new file mode 100644 index 0000000..deaf68e --- /dev/null +++ b/src/kernel/cpu.h @@ -0,0 +1,40 @@ +#pragma once + + +class cpu_id +{ +public: + struct regs { + uint32_t eax, ebx, ecx, edx; + + regs() : eax(0), ebx(0), ecx(0), edx(0) {} + regs(uint32_t a, uint32_t b, uint32_t c, uint32_t d) : eax(a), ebx(b), ecx(c), edx(d) {} + regs(const regs &r) : eax(r.eax), ebx(r.ebx), ecx(r.ecx), edx(r.edx) {} + + bool eax_bit(unsigned bit) { return (eax >> bit) & 0x1; } + bool ebx_bit(unsigned bit) { return (ebx >> bit) & 0x1; } + bool ecx_bit(unsigned bit) { return (ecx >> bit) & 0x1; } + bool edx_bit(unsigned bit) { return (edx >> bit) & 0x1; } + }; + + cpu_id(); + + regs get(uint32_t leaf, uint32_t sub = 0) const; + + inline const char * vendor_id() const { return m_vendor_id; } + inline uint8_t cpu_type() const { return m_cpu_type; } + inline uint8_t stepping() const { return m_stepping; } + inline uint16_t family() const { return m_family; } + inline uint16_t model() const { return m_model; } + +private: + void read(); + + uint32_t m_high_leaf; + char m_vendor_id[13]; + + uint8_t m_cpu_type; + uint8_t m_stepping; + uint16_t m_family; + uint16_t m_model; +}; diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 644d184..9f5ad58 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -3,6 +3,7 @@ #include "kutil/memory.h" #include "console.h" +#include "cpu.h" #include "device_manager.h" #include "font.h" #include "interrupts.h" @@ -48,6 +49,18 @@ kernel_main(popcorn_data *header) log::init(cons); + cpu_id cpu; + + log::info(logs::boot, "CPU Vendor: %s", cpu.vendor_id()); + log::info(logs::boot, "CPU Family %x Model %x Stepping %x", + cpu.family(), cpu.model(), cpu.stepping()); + + cpu_id::regs cpu_info = cpu.get(1); + log::info(logs::boot, "LAPIC Supported: %s", + cpu_info.edx_bit(9) ? "yes" : "no"); + log::info(logs::boot, "x2APIC Supported: %s", + cpu_info.ecx_bit(21) ? "yes" : "no"); + page_manager *pager = new (&g_page_manager) page_manager; pager->mark_offset_pointer(&header->frame_buffer, header->frame_buffer_length);