diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2023-04-23 17:55:16 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2023-04-23 17:55:16 -0400 |
commit | 1f0c894080e0a3d62694a056456e378e36eb12a1 (patch) | |
tree | 7abd3928808aa9f03a4dd17dd3eb5ecde7607d18 /x86.c | |
parent | 0ec45301dc4d1a61cc1d9bd2906cd010c88f81c0 (diff) | |
download | whatami-1f0c894080e0a3d62694a056456e378e36eb12a1.tar.gz |
Refactor
Split linux, darwin, and x86 into separate modules
Diffstat (limited to 'x86.c')
-rw-r--r-- | x86.c | 117 |
1 files changed, 117 insertions, 0 deletions
@@ -0,0 +1,117 @@ +#include "common.h" + +/*** + * + * @param leaf + * @param reg union regs_t + * @return contents of eax register + */ +unsigned int CPUID(unsigned int leaf, union regs_t *reg) { + memset(reg, 0, sizeof(*reg)); + __get_cpuid(leaf, ®->gpr.eax, ®->gpr.ebx, ®->gpr.ecx, ®->gpr.edx); + return reg->gpr.eax; +} + +int is_cpu_hyperthreaded() { + union regs_t reg; + + CPUID(1, ®); + // Hyperthreading feature flag is located in bit 28 of EDX (regs[3]) + if (reg.gpr.edx & bit_HTT) { + // hyperthreaded + return 1; + } + return 0; +} + +int is_cpu_virtual() { + union regs_t reg; + + CPUID(1, ®); + // Virtualization flag is located in bit 31 of ECX + if (reg.gpr.ecx & bit_VRT) { + return 1; + } + return 0; +} + +char *get_sys_product() { + union regs_t reg; + char *vendor; + + vendor = NULL; + if (is_cpu_virtual()) { + vendor = calloc(255, sizeof(*vendor)); + if (!vendor) { + return NULL; + } + CPUID(0x40000000, ®); + strncat(vendor, (char *) ®.bytes[1], sizeof(reg.bytes)); + rstrip(vendor); + } +#if defined(__linux__) + if (!vendor || !strlen(vendor)) { + vendor = get_sys_dmi_product(); + rstrip(vendor); + } +#elif defined(__APPLE__) + if (!vendor || !strlen(vendor)) { + vendor = get_sys_product_darwin(); + rstrip(vendor); + } +#endif + return vendor; +} + +unsigned int get_cpu_count() { + union regs_t reg; + unsigned int result; + + if (is_cpu_hyperthreaded()) { + CPUID(1, ®); + // cpu count is located in bits 16:23 of EBX + result = reg.gpr.ebx >> 16 & 0xff; + } else { // Legacy check + // Core Count is located in 0:7 of ECX + CPUID(0x80000008, ®); + result = 1 + (reg.gpr.ecx & 0xff); + } + +#if defined(__linux__) || (defined(__APPLE__) || defined(TARGET_OS_MAC)) + if (result == 1) { + // One CPU might indicate we were unable to poll the information + // See what the kernel thinks + result = sysconf(_SC_NPROCESSORS_ONLN); + } +#endif + return result; +} + +char *get_cpu_manufacturer() { + union regs_t reg; + char *manufacturer; + + CPUID(0, ®); + manufacturer = calloc(sizeof(reg.bytes), sizeof(*reg.bytes)); + if (!manufacturer) { + return NULL; + } + strncat(manufacturer, (char *) ®.bytes[1], 4); + strncat(manufacturer, (char *) ®.bytes[3], 4); + strncat(manufacturer, (char *) ®.bytes[2], 4); + return manufacturer; +} + +char *get_cpu_vendor() { + union regs_t reg; + char *vendor; + + vendor = calloc(sizeof(reg.bytes) * 3, sizeof(*reg.bytes)); + for (unsigned int leaf = 2; leaf < 5; leaf++) { + CPUID(0x80000000 + leaf, ®); + strncat(vendor, (char *) reg.bytes, sizeof(reg.bytes)); + } + + rstrip(vendor); + return vendor; +} |