From 11f76ab01d3509b78b9ed6c76ac732e1c091d2e6 Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 29 Sep 2024 11:21:21 -0300 Subject: [PATCH] cpuid: better implementation --- kernel-src/arch/x86-64/cpu.c | 36 +--------- kernel-src/include/x86-64/arch/cpuid.h | 98 ++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 34 deletions(-) create mode 100644 kernel-src/include/x86-64/arch/cpuid.h diff --git a/kernel-src/arch/x86-64/cpu.c b/kernel-src/arch/x86-64/cpu.c index 0bfa46da..25bfecb5 100644 --- a/kernel-src/arch/x86-64/cpu.c +++ b/kernel-src/arch/x86-64/cpu.c @@ -2,12 +2,8 @@ #include #include #include +#include -#define CPUID_VENDOR_AMD "AuthenticAMD" -#define CPUID_VENDOR_INTEL "GenuineIntel" - -#define CPUID_SYSCALL (1 << 11) -#define CPUID_LEAF_1_EDX_HTT (1 << 28) #define EFER_SYSCALLENABLE 1 void arch_syscall_entry(); @@ -43,34 +39,6 @@ static void x87isr(isr_t *self, context_t *ctx) { } } -static bool cpuid_leaf_0xb_available(void) { - if (current_cpu()->cpuid_max < 0xb) - return false; - - unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; - __get_cpuid_count(0xb, 0, &eax, &ebx, &ecx, &edx); - return ebx != 0; -} - -static bool cpuid_leaf_0x80000008_available(void) { - unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; - __get_cpuid(0x80000000, &eax, &ebx, &ecx, &edx); - - if (eax < 0x80000008) - return false; - - return true; -} - -static bool cpuid_leaf_0x4_available(void) { - if (current_cpu()->cpuid_max < 0x4) - return false; - - unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; - __get_cpuid_count(0xb, 0, &eax, &ebx, &ecx, &edx); - return eax != 0; -} - #define TOPOLOGY_TYPE_THREAD 1 #define TOPOLOGY_TYPE_CORE 2 #define TOPOLOGY_TYPE_PACKAGE 0xffffffff @@ -183,7 +151,7 @@ void cpu_initstate() { unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; __get_cpuid(0x80000001, &eax, &ebx, &ecx, &edx); - __assert(edx & CPUID_SYSCALL); + __assert(edx & CPUID_LEAF_0x80000001_EDX_SYSCALL); uint64_t efer = rdmsr(MSR_EFER); efer |= EFER_SYSCALLENABLE; wrmsr(MSR_EFER, efer); diff --git a/kernel-src/include/x86-64/arch/cpuid.h b/kernel-src/include/x86-64/arch/cpuid.h new file mode 100644 index 00000000..4b47b47a --- /dev/null +++ b/kernel-src/include/x86-64/arch/cpuid.h @@ -0,0 +1,98 @@ +#ifndef _CPUID_H +#define _CPUID_H + +typedef struct { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +} cpuid_results_t; + +#define CPUID_HYPERVISOR_KVM_EBX 0x4b4d564b +#define CPUID_HYPERVISOR_KVM_ECX 0x564b4d56 +#define CPUID_HYPERVISOR_KVM_EDX 0x4d + +#define CPUID_HYPERVISOR_IS_KVM(ebx, ecx, edx) ((ebx) == CPUID_HYPERVISOR_KVM && (ecx) == CPUID_HYPERVISOR_KVM_ECX && (edx) == CPUID_HYPERVISOR_KVM_EDX) + +#define CPUID_VENDOR_AMD "AuthenticAMD" +#define CPUID_VENDOR_INTEL "GenuineIntel" + +#define CPUID_LEAF_0x80000001_EDX_SYSCALL (1 << 11) +#define CPUID_LEAF_1_EDX_HTT (1 << 28) + +static inline void cpuid_with_ecx(uint32_t leaf, uint32_t ecx, cpuid_results_t *cpuid_results) { + asm volatile ("cpuid" + : + "=a"(cpuid_results->eax), + "=b"(cpuid_results->ebx), + "=c"(cpuid_results->ecx), + "=d"(cpuid_results->edx) + : + "a"(leaf), + "c"(ecx)); +} + +static inline void cpuid(uint32_t leaf, cpuid_results_t *cpuid_results) { + return cpuid_with_ecx(leaf, 0, cpuid_results); +} + +static inline uint32_t cpuid_find_hypervisor_base(uint32_t ebx, uint32_t ecx, uint32_t edx) { + uint32_t return_base = 0; + cpuid_results_t cpuid_results = {0}; + + for (uint32_t base = 0x40000000; base < 0x40001000; base += 0x100) { + cpuid(base, &cpuid_results); + if (cpuid_results.ebx == ebx && cpuid_results.ecx == ecx && cpuid_results.edx == edx) { + return_base = base; + break; + } + } + + return return_base; +} + +static inline uint32_t cpuid_find_hypervisor_base_kvm(void) { + return cpuid_find_hypervisor_base(CPUID_HYPERVISOR_KVM_EBX, CPUID_HYPERVISOR_KVM_ECX, CPUID_HYPERVISOR_KVM_EDX); +} + +static inline uint32_t cpuid_base_max_leaf(void) { + cpuid_results_t cpuid_results; + cpuid(0, &cpuid_results); + return cpuid_results.eax; +} + +static inline uint32_t cpuid_hypervisor_max_leaf(uint32_t base) { + cpuid_results_t cpuid_results; + cpuid(base, &cpuid_results); + return cpuid_results.eax; +} + +static inline uint32_t cpuid_extended_max_leaf(void) { + cpuid_results_t cpuid_results; + cpuid(0x80000000, &cpuid_results); + return cpuid_results.eax; +} + +static inline bool cpuid_leaf_0xb_available(void) { + if (cpuid_base_max_leaf() < 0xb) + return false; + + cpuid_results_t cpuid_results; + cpuid(0xb, &cpuid_results); + return cpuid_results.ebx != 0; +} + +static inline bool cpuid_leaf_0x80000008_available(void) { + return cpuid_extended_max_leaf() >= 0x80000008; +} + +static inline bool cpuid_leaf_0x4_available(void) { + if (cpuid_base_max_leaf() < 0x4) + return false; + + unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0; + __get_cpuid_count(0x4, 0, &eax, &ebx, &ecx, &edx); + return eax != 0; +} + +#endif