:github_url: https://github.com/nyx-org/gaia .. _program_listing_file_platform_amd64_cpuid.hpp: Program Listing for File cpuid.hpp ================================== |exhale_lsh| :ref:`Return to documentation for file ` (``platform/amd64/cpuid.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include namespace Gaia::Amd64 { #define CPUID_LEAF_EXTENDED_FEATURES 0x80000001 #define CPUID_PROC_EXTENDED_STATE_ENUMERATION 13 struct Cpuid { uint32_t eax; uint32_t ebx; uint32_t ecx; uint32_t edx; static inline Result cpuid(uint32_t leaf = 0, uint32_t subleaf = 0) { uint32_t cpuid_max; Cpuid ret; asm volatile("cpuid" : "=a"(cpuid_max) : "a"(leaf & 0x80000000) : "rbx", "rcx", "rdx"); if (leaf > cpuid_max) { return Err(Error::INVALID_PARAMETERS); } asm volatile("cpuid" : "=a"(ret.eax), "=b"(ret.ebx), "=c"(ret.ecx), "=d"(ret.edx) : "a"(leaf), "c"(subleaf)); return Ok(ret); } enum class Feature : uint32_t { ECX_SSE3 = 1 << 0, ECX_PCLMUL = 1 << 1, ECX_DTES64 = 1 << 2, ECX_MONITOR = 1 << 3, ECX_DS_CPL = 1 << 4, ECX_VMX = 1 << 5, ECX_SMX = 1 << 6, ECX_EST = 1 << 7, ECX_TM2 = 1 << 8, ECX_SSSE3 = 1 << 9, ECX_CID = 1 << 10, ECX_SDBG = 1 << 11, ECX_FMA = 1 << 12, ECX_CX16 = 1 << 13, ECX_XTPR = 1 << 14, ECX_PDCM = 1 << 15, ECX_PCID = 1 << 17, ECX_DCA = 1 << 18, ECX_SSE4_1 = 1 << 19, ECX_SSE4_2 = 1 << 20, ECX_X2APIC = 1 << 21, ECX_MOVBE = 1 << 22, ECX_POPCNT = 1 << 23, ECX_TSC = 1 << 24, ECX_AES = 1 << 25, ECX_XSAVE = 1 << 26, ECX_OSXSAVE = 1 << 27, ECX_AVX = 1 << 28, ECX_F16C = 1 << 29, ECX_RDRAND = 1 << 30, ECX_HYPERVISOR = 1U << 31, EDX_FPU = 1 << 0, EDX_VME = 1 << 1, EDX_DE = 1 << 2, EDX_PSE = 1 << 3, EDX_TSC = 1 << 4, EDX_MSR = 1 << 5, EDX_PAE = 1 << 6, EDX_MCE = 1 << 7, EDX_CX8 = 1 << 8, EDX_APIC = 1 << 9, EDX_SEP = 1 << 11, EDX_MTRR = 1 << 12, EDX_PGE = 1 << 13, EDX_MCA = 1 << 14, EDX_CMOV = 1 << 15, EDX_PAT = 1 << 16, EDX_PSE36 = 1 << 17, EDX_PSN = 1 << 18, EDX_CLFLUSH = 1 << 19, EDX_DS = 1 << 21, EDX_ACPI = 1 << 22, EDX_MMX = 1 << 23, EDX_FXSR = 1 << 24, EDX_SSE = 1 << 25, EDX_SSE2 = 1 << 26, EDX_SS = 1 << 27, EDX_HTT = 1 << 28, EDX_TM = 1 << 29, EDX_IA64 = 1 << 30, EDX_PBE = 1U << 31 }; enum class ExFeature : uint32_t { FPU = 1 << 0, VME = 1 << 1, DE = 1 << 2, PSE = 1 << 3, TSC = 1 << 4, MSR = 1 << 5, PAE = 1 << 6, MCE = 1 << 7, CX8 = 1 << 8, APIC = 1 << 9, SYSCALL = 1 << 11, MTRR = 1 << 12, PGE = 1 << 13, MCA = 1 << 14, CMOV = 1 << 15, PAT = 1 << 16, PSE36 = 1 << 17, MP = 1 << 19, NX = 1 << 20, MMXEXT = 1 << 22, MMX = 1 << 23, FXSR = 1 << 24, FXSR_OPT = 1 << 25, PDPE1GB = 1 << 26, RDTSCP = 1 << 27, }; static inline bool has_exfeature(ExFeature feat) { return cpuid(CPUID_LEAF_EXTENDED_FEATURES, 0).unwrap().edx & (uint32_t)feat; } static inline bool has_ecx_feature(Feature feat) { return cpuid(0x1, 0).unwrap().ecx & (uint32_t)feat; } static inline bool has_edx_feature(Feature feat) { return cpuid(0x1, 0).unwrap().edx & (uint32_t)feat; } static frg::array _vendor() { union { frg::array regs; frg::array str; } brand{}; auto ret = cpuid(0).unwrap(); brand.regs[0] = ret.ebx; brand.regs[1] = ret.edx; brand.regs[2] = ret.ecx; return brand.str; } static frg::array _brand() { union { frg::array ids; frg::array str; } brand{}; brand.ids[0] = cpuid(0x80000002).unwrap(); brand.ids[1] = cpuid(0x80000003).unwrap(); brand.ids[2] = cpuid(0x80000004).unwrap(); brand.ids[3] = cpuid(0x80000005).unwrap(); return brand.str; } struct Branding { frg::string_view vendor, brand; }; static Branding branding() { return {_vendor().data(), _brand().data()}; } }; } // namespace Gaia::Amd64