aboutsummaryrefslogtreecommitdiff
path: root/x86.c
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2023-04-23 17:55:16 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2023-04-23 17:55:16 -0400
commit1f0c894080e0a3d62694a056456e378e36eb12a1 (patch)
tree7abd3928808aa9f03a4dd17dd3eb5ecde7607d18 /x86.c
parent0ec45301dc4d1a61cc1d9bd2906cd010c88f81c0 (diff)
downloadwhatami-1f0c894080e0a3d62694a056456e378e36eb12a1.tar.gz
Refactor
Split linux, darwin, and x86 into separate modules
Diffstat (limited to 'x86.c')
-rw-r--r--x86.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/x86.c b/x86.c
new file mode 100644
index 0000000..647d6ac
--- /dev/null
+++ b/x86.c
@@ -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, &reg->gpr.eax, &reg->gpr.ebx, &reg->gpr.ecx, &reg->gpr.edx);
+ return reg->gpr.eax;
+}
+
+int is_cpu_hyperthreaded() {
+ union regs_t reg;
+
+ CPUID(1, &reg);
+ // 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, &reg);
+ // 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, &reg);
+ strncat(vendor, (char *) &reg.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, &reg);
+ // 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, &reg);
+ 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, &reg);
+ manufacturer = calloc(sizeof(reg.bytes), sizeof(*reg.bytes));
+ if (!manufacturer) {
+ return NULL;
+ }
+ strncat(manufacturer, (char *) &reg.bytes[1], 4);
+ strncat(manufacturer, (char *) &reg.bytes[3], 4);
+ strncat(manufacturer, (char *) &reg.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, &reg);
+ strncat(vendor, (char *) reg.bytes, sizeof(reg.bytes));
+ }
+
+ rstrip(vendor);
+ return vendor;
+}