2024-03-08 17:26:35 +05:30
|
|
|
/*
|
|
|
|
* cpuid_vendor_id.mod.c
|
|
|
|
*
|
|
|
|
* The file is a modified version of a gist "cpuid_vendor_id.c" by leiless:
|
|
|
|
* https://gist.github.com/leiless/8b8603ae31c00fe38d2e97d94462a5a5
|
|
|
|
* (revision 73830d4b10090dcf6748cc60a0aacee252cd9e9d2dd54549aa7b995321380091)
|
|
|
|
*
|
|
|
|
* The following license information applies for the modifications:
|
|
|
|
* Author: Intel A80486DX2-66
|
|
|
|
* License: Creative Commons Zero 1.0 Universal
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if !(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || \
|
|
|
|
defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) || \
|
|
|
|
defined(__i386) || defined(__i386__) || defined(__IA32__) || \
|
|
|
|
defined(_M_I86) || defined(_M_IX86) || defined(__X86__) || defined(_X86_))
|
|
|
|
# error "This code isn't supposed to work on non-x86 CPUs."
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#include <intrin.h> // __cpuid()
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef unsigned int cpuid_t[4];
|
|
|
|
|
|
|
|
#define EAX 0
|
|
|
|
#define EBX 1
|
|
|
|
#define ECX 2
|
|
|
|
#define EDX 3
|
|
|
|
|
|
|
|
// https://elixir.bootlin.com/linux/latest/source/arch/x86/include/asm/
|
|
|
|
// processor.h#L216
|
|
|
|
//
|
|
|
|
// https://stackoverflow.com/questions/6491566/getting-the-machine-serial
|
|
|
|
// -number-and-cpu-id-using-c-c-in-linux
|
|
|
|
//
|
|
|
|
// https://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
|
|
|
|
static inline void native_cpuid(unsigned int function_id, cpuid_t r) {
|
|
|
|
#ifdef _WIN32
|
2024-03-08 22:10:54 +05:30
|
|
|
__cpuid((int *) r, (int) function_id);
|
2024-03-08 17:26:35 +05:30
|
|
|
#else
|
2024-03-08 22:10:54 +05:30
|
|
|
r[EAX] = function_id;
|
|
|
|
r[ECX] = 0;
|
2024-03-08 17:26:35 +05:30
|
|
|
|
2024-03-08 22:10:54 +05:30
|
|
|
// NOTE:XXX: Register ECX is often an input as well as an output
|
|
|
|
asm volatile("cpuid"
|
|
|
|
: "=a" (r[EAX]),
|
|
|
|
"=b" (r[EBX]),
|
|
|
|
"=c" (r[ECX]),
|
|
|
|
"=d" (r[EDX])
|
|
|
|
: "0" (r[EAX]), "2" (r[ECX])
|
|
|
|
: "memory");
|
2024-03-08 17:26:35 +05:30
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VENDOR_ID_LEN 13
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FIXME: you have to make sure the vendor argument is at least lengthed
|
|
|
|
* VENDOR_ID_LEN
|
|
|
|
*/
|
|
|
|
static inline void cpuid_vendor_id(char vendor[VENDOR_ID_LEN]) {
|
2024-03-08 22:10:54 +05:30
|
|
|
// Always initialize the result in case of buggy CPU (like ES/QS CPUs)
|
|
|
|
cpuid_t v;
|
|
|
|
native_cpuid(0, v);
|
2024-03-08 17:26:35 +05:30
|
|
|
|
2024-03-08 22:10:54 +05:30
|
|
|
// https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex
|
2024-03-08 17:26:35 +05:30
|
|
|
// ?view=msvc-170#example
|
2024-03-08 22:10:54 +05:30
|
|
|
((unsigned int *) vendor)[0] = v[EBX];
|
|
|
|
((unsigned int *) vendor)[1] = v[EDX];
|
|
|
|
((unsigned int *) vendor)[2] = v[ECX];
|
|
|
|
vendor[VENDOR_ID_LEN - 1] = '\0';
|
2024-03-08 17:26:35 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
int main(void) {
|
2024-03-08 22:10:54 +05:30
|
|
|
char vendor_string[VENDOR_ID_LEN];
|
|
|
|
cpuid_vendor_id(vendor_string);
|
|
|
|
printf("CPU Vendor ID: '%s'\n", vendor_string);
|
|
|
|
return 0;
|
2024-03-08 17:26:35 +05:30
|
|
|
}
|