aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@gmail.com>2018-02-19 22:43:26 -0800
committerMarat Dukhan <maratek@gmail.com>2018-02-19 22:48:12 -0800
commitb2fc4ab8099b802de934f24adf2da6e4c863bd3c (patch)
treee2e22022cc4d4d1de9eba0e6628f127e7e8806ee
parenta9e55a6afde89722af7ee30dc7bd27435e96226b (diff)
downloadcpuinfo-b2fc4ab8099b802de934f24adf2da6e4c863bd3c.tar.gz
Windows support
-rw-r--r--CMakeLists.txt8
-rw-r--r--include/cpuinfo.h9
-rw-r--r--src/api.h7
-rw-r--r--src/init.c14
-rw-r--r--src/log.c12
-rw-r--r--src/utils.h8
-rw-r--r--src/x86/api.h80
-rw-r--r--src/x86/cache/descriptor.c32
-rw-r--r--src/x86/cache/deterministic.c6
-rw-r--r--src/x86/cache/init.c32
-rw-r--r--src/x86/cpuid.h10
-rw-r--r--src/x86/init.c2
-rw-r--r--src/x86/isa.c18
-rw-r--r--src/x86/linux/api.h3
-rw-r--r--src/x86/name.c8
-rw-r--r--src/x86/topology.c2
-rw-r--r--src/x86/uarch.c2
-rw-r--r--src/x86/windows/api.h41
-rw-r--r--src/x86/windows/init.c573
-rw-r--r--tools/cache-info.c2
-rw-r--r--tools/cpu-info.c33
21 files changed, 788 insertions, 114 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4e55cf6..756ce44 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,13 +28,13 @@ IF(NOT CMAKE_SYSTEM_PROCESSOR)
IF(NOT IOS)
MESSAGE(FATAL_ERROR "CMAKE_SYSTEM_PROCESSOR not defined")
ENDIF()
-ELSEIF(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64|armv5te|armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|arm64|aarch64)$")
+ELSEIF(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|AMD64|x86_64|armv5te|armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|arm64|aarch64)$")
MESSAGE(FATAL_ERROR "Unrecognized CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
ENDIF()
IF(NOT CMAKE_SYSTEM_NAME)
MESSAGE(FATAL_ERROR "CMAKE_SYSTEM_NAME not defined")
-ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Darwin|Linux|Android)$")
+ELSEIF(NOT CMAKE_SYSTEM_NAME MATCHES "^(Windows|Darwin|Linux|Android)$")
MESSAGE(FATAL_ERROR "Unrecognized CMAKE_SYSTEM_NAME = ${CMAKE_SYSTEM_NAME}")
ENDIF()
@@ -72,7 +72,7 @@ SET(CPUINFO_SRCS
src/api.c
src/log.c)
-IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64)$")
+IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64|AMD64)$")
LIST(APPEND CPUINFO_SRCS
src/x86/init.c
src/x86/info.c
@@ -90,6 +90,8 @@ IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64)$")
src/x86/linux/cpuinfo.c)
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
LIST(APPEND CPUINFO_SRCS src/x86/mach/init.c)
+ ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+ LIST(APPEND CPUINFO_SRCS src/x86/windows/init.c)
ENDIF()
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7|armv7f|armv7s|armv7k|armv7-a|armv7l|arm64|aarch64)$" OR IOS)
LIST(APPEND CPUINFO_SRCS
diff --git a/include/cpuinfo.h b/include/cpuinfo.h
index cae8af9..a9a49e4 100644
--- a/include/cpuinfo.h
+++ b/include/cpuinfo.h
@@ -424,6 +424,15 @@ struct cpuinfo_processor {
*/
int linux_id;
#endif
+#if defined(_WIN32)
+ /** Windows-specific ID for the group containing the logical processor. */
+ uint16_t windows_group_id;
+ /**
+ * Windows-specific ID of the logical processor within its group:
+ * - Bit <windows_processor_id> in the KAFFINITY mask identifies this logical processor within its group.
+ */
+ uint16_t windows_processor_id;
+#endif
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
/** APIC ID (unique x86-specific ID of the logical processor) */
uint32_t apic_id;
diff --git a/src/api.h b/src/api.h
index 8a657ab..49985ed 100644
--- a/src/api.h
+++ b/src/api.h
@@ -5,6 +5,10 @@
#include <cpuinfo.h>
+#ifdef _WIN32
+ #include <windows.h>
+#endif
+
enum cpuinfo_cache_level {
cpuinfo_cache_level_1i = 0,
cpuinfo_cache_level_1d = 1,
@@ -25,6 +29,9 @@ extern uint32_t cpuinfo_cache_count[cpuinfo_cache_level_max];
void cpuinfo_x86_mach_init(void);
void cpuinfo_x86_linux_init(void);
+#ifdef _WIN32
+ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context);
+#endif
void cpuinfo_arm_mach_init(void);
void cpuinfo_arm_linux_init(void);
diff --git a/src/init.c b/src/init.c
index 8a88ce5..a877f23 100644
--- a/src/init.c
+++ b/src/init.c
@@ -1,4 +1,8 @@
-#include <pthread.h>
+#ifdef _WIN32
+ #include <windows.h>
+#else
+ #include <pthread.h>
+#endif
#include <cpuinfo.h>
#include <api.h>
@@ -17,7 +21,11 @@ uint32_t cpuinfo_cores_count = 0;
uint32_t cpuinfo_packages_count = 0;
-static pthread_once_t init_guard = PTHREAD_ONCE_INIT;
+#ifdef _WIN32
+ static INIT_ONCE init_guard = INIT_ONCE_STATIC_INIT;
+#else
+ static pthread_once_t init_guard = PTHREAD_ONCE_INIT;
+#endif
void CPUINFO_ABI cpuinfo_initialize(void) {
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
@@ -25,6 +33,8 @@ void CPUINFO_ABI cpuinfo_initialize(void) {
pthread_once(&init_guard, &cpuinfo_x86_mach_init);
#elif defined(__linux__)
pthread_once(&init_guard, &cpuinfo_x86_linux_init);
+ #elif defined(_WIN32)
+ InitOnceExecuteOnce(&init_guard, &cpuinfo_x86_windows_init, NULL, NULL);
#else
#error Unsupported target OS
#endif
diff --git a/src/log.c b/src/log.c
index 3e6d8bb..65fac8c 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,6 +1,8 @@
#include <stdarg.h>
#include <stdio.h>
-#include <unistd.h>
+#ifndef _WIN32
+ #include <unistd.h>
+#endif
#include <log.h>
@@ -9,7 +11,7 @@
va_list args;
va_start(args, format);
- #ifdef __ANDROID__
+ #if defined(__ANDROID__) || defined(_WIN32)
fprintf(stderr, "Error: ");
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
@@ -29,7 +31,7 @@
va_list args;
va_start(args, format);
- #ifdef __ANDROID__
+ #if defined(__ANDROID__) || defined(_WIN32)
fprintf(stderr, "Warning: ");
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
@@ -49,7 +51,7 @@
va_list args;
va_start(args, format);
- #ifdef __ANDROID__
+ #if defined(__ANDROID__) || defined(_WIN32)
printf("Note: ");
vprintf(format, args);
printf("\n");
@@ -68,7 +70,7 @@
va_list args;
va_start(args, format);
- #ifdef __ANDROID__
+ #if defined(__ANDROID__) || defined(_WIN32)
printf("Debug: ");
vprintf(format, args);
printf("\n");
diff --git a/src/utils.h b/src/utils.h
index 46ba9d9..157baad 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -8,6 +8,12 @@ inline static uint32_t bit_length(uint32_t n) {
if (n_minus_1 == 0) {
return 0;
} else {
- return 32 - __builtin_clz(n_minus_1);
+ #ifdef _MSC_VER
+ unsigned long bsr;
+ _BitScanReverse(&bsr, n_minus_1);
+ return bsr + 1;
+ #else
+ return 32 - __builtin_clz(n_minus_1);
+ #endif
}
}
diff --git a/src/x86/api.h b/src/x86/api.h
index 9c691b7..fe9d527 100644
--- a/src/x86/api.h
+++ b/src/x86/api.h
@@ -80,13 +80,13 @@ struct cpuinfo_x86_processor {
char brand_string[CPUINFO_PACKAGE_NAME_MAX];
};
-void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor processor[restrict static 1]);
+void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor);
enum cpuinfo_vendor cpuinfo_x86_decode_vendor(uint32_t ebx, uint32_t ecx, uint32_t edx);
struct cpuinfo_x86_model_info cpuinfo_x86_decode_model_info(uint32_t eax);
enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
enum cpuinfo_vendor vendor,
- const struct cpuinfo_x86_model_info model_info[restrict static 1]);
+ const struct cpuinfo_x86_model_info* model_info);
struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
const struct cpuid_regs basic_info, const struct cpuid_regs extended_info,
@@ -98,57 +98,57 @@ void cpuinfo_x86_detect_topology(
uint32_t max_base_index,
uint32_t max_extended_index,
struct cpuid_regs leaf1,
- struct cpuinfo_x86_topology topology[restrict static 1]);
+ struct cpuinfo_x86_topology* topology);
void cpuinfo_x86_detect_cache(
uint32_t max_base_index, uint32_t max_extended_index,
bool amd_topology_extensions,
enum cpuinfo_vendor vendor,
- const struct cpuinfo_x86_model_info model_info[restrict static 1],
- struct cpuinfo_x86_caches cache[restrict static 1],
- struct cpuinfo_tlb itlb_4KB[restrict static 1],
- struct cpuinfo_tlb itlb_2MB[restrict static 1],
- struct cpuinfo_tlb itlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb0_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_1GB[restrict static 1],
- struct cpuinfo_tlb stlb2_4KB[restrict static 1],
- struct cpuinfo_tlb stlb2_2MB[restrict static 1],
- struct cpuinfo_tlb stlb2_1GB[restrict static 1],
- uint32_t log2_package_cores_max[restrict static 1]);
+ const struct cpuinfo_x86_model_info* model_info,
+ struct cpuinfo_x86_caches* cache,
+ struct cpuinfo_tlb* itlb_4KB,
+ struct cpuinfo_tlb* itlb_2MB,
+ struct cpuinfo_tlb* itlb_4MB,
+ struct cpuinfo_tlb* dtlb0_4KB,
+ struct cpuinfo_tlb* dtlb0_2MB,
+ struct cpuinfo_tlb* dtlb0_4MB,
+ struct cpuinfo_tlb* dtlb_4KB,
+ struct cpuinfo_tlb* dtlb_2MB,
+ struct cpuinfo_tlb* dtlb_4MB,
+ struct cpuinfo_tlb* dtlb_1GB,
+ struct cpuinfo_tlb* stlb2_4KB,
+ struct cpuinfo_tlb* stlb2_2MB,
+ struct cpuinfo_tlb* stlb2_1GB,
+ uint32_t* log2_package_cores_max);
void cpuinfo_x86_decode_cache_descriptor(
uint8_t descriptor, enum cpuinfo_vendor vendor,
- const struct cpuinfo_x86_model_info model_info[restrict static 1],
- struct cpuinfo_x86_caches cache[restrict static 1],
- struct cpuinfo_tlb itlb_4KB[restrict static 1],
- struct cpuinfo_tlb itlb_2MB[restrict static 1],
- struct cpuinfo_tlb itlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb0_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_1GB[restrict static 1],
- struct cpuinfo_tlb stlb2_4KB[restrict static 1],
- struct cpuinfo_tlb stlb2_2MB[restrict static 1],
- struct cpuinfo_tlb stlb2_1GB[restrict static 1],
- uint32_t prefetch_size[restrict static 1]);
+ const struct cpuinfo_x86_model_info* model_info,
+ struct cpuinfo_x86_caches* cache,
+ struct cpuinfo_tlb* itlb_4KB,
+ struct cpuinfo_tlb* itlb_2MB,
+ struct cpuinfo_tlb* itlb_4MB,
+ struct cpuinfo_tlb* dtlb0_4KB,
+ struct cpuinfo_tlb* dtlb0_2MB,
+ struct cpuinfo_tlb* dtlb0_4MB,
+ struct cpuinfo_tlb* dtlb_4KB,
+ struct cpuinfo_tlb* dtlb_2MB,
+ struct cpuinfo_tlb* dtlb_4MB,
+ struct cpuinfo_tlb* dtlb_1GB,
+ struct cpuinfo_tlb* stlb2_4KB,
+ struct cpuinfo_tlb* stlb2_2MB,
+ struct cpuinfo_tlb* stlb2_1GB,
+ uint32_t* prefetch_size);
bool cpuinfo_x86_decode_deterministic_cache_parameters(
struct cpuid_regs regs,
- struct cpuinfo_x86_caches cache[restrict static 1],
- uint32_t package_cores_max[restrict static 1]);
+ struct cpuinfo_x86_caches* cache,
+ uint32_t* package_cores_max);
bool cpuinfo_x86_decode_cache_properties(
struct cpuid_regs regs,
- struct cpuinfo_x86_caches cache[restrict static 1]);
+ struct cpuinfo_x86_caches* cache);
uint32_t cpuinfo_x86_normalize_brand_string(
- const char raw_name[restrict static 48],
- char normalized_name[restrict static 48]);
+ const char raw_name[48],
+ char normalized_name[48]);
diff --git a/src/x86/cache/descriptor.c b/src/x86/cache/descriptor.c
index 28e18ce..adba372 100644
--- a/src/x86/cache/descriptor.c
+++ b/src/x86/cache/descriptor.c
@@ -6,22 +6,22 @@
void cpuinfo_x86_decode_cache_descriptor(
uint8_t descriptor, enum cpuinfo_vendor vendor,
- const struct cpuinfo_x86_model_info model_info[restrict static 1],
- struct cpuinfo_x86_caches cache[restrict static 1],
- struct cpuinfo_tlb itlb_4KB[restrict static 1],
- struct cpuinfo_tlb itlb_2MB[restrict static 1],
- struct cpuinfo_tlb itlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb0_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_1GB[restrict static 1],
- struct cpuinfo_tlb stlb2_4KB[restrict static 1],
- struct cpuinfo_tlb stlb2_2MB[restrict static 1],
- struct cpuinfo_tlb stlb2_1GB[restrict static 1],
- uint32_t prefetch_size[restrict static 1])
+ const struct cpuinfo_x86_model_info* model_info,
+ struct cpuinfo_x86_caches* cache,
+ struct cpuinfo_tlb* itlb_4KB,
+ struct cpuinfo_tlb* itlb_2MB,
+ struct cpuinfo_tlb* itlb_4MB,
+ struct cpuinfo_tlb* dtlb0_4KB,
+ struct cpuinfo_tlb* dtlb0_2MB,
+ struct cpuinfo_tlb* dtlb0_4MB,
+ struct cpuinfo_tlb* dtlb_4KB,
+ struct cpuinfo_tlb* dtlb_2MB,
+ struct cpuinfo_tlb* dtlb_4MB,
+ struct cpuinfo_tlb* dtlb_1GB,
+ struct cpuinfo_tlb* stlb2_4KB,
+ struct cpuinfo_tlb* stlb2_2MB,
+ struct cpuinfo_tlb* stlb2_1GB,
+ uint32_t* prefetch_size)
{
/*
* Descriptors are parsed according to:
diff --git a/src/x86/cache/deterministic.c b/src/x86/cache/deterministic.c
index d551398..2cd5827 100644
--- a/src/x86/cache/deterministic.c
+++ b/src/x86/cache/deterministic.c
@@ -15,8 +15,8 @@ enum cache_type {
bool cpuinfo_x86_decode_deterministic_cache_parameters(
struct cpuid_regs regs,
- struct cpuinfo_x86_caches cache[restrict static 1],
- uint32_t package_cores_max[restrict static 1])
+ struct cpuinfo_x86_caches* cache,
+ uint32_t* package_cores_max)
{
const uint32_t type = regs.eax & UINT32_C(0x1F);
if (type == cache_type_none) {
@@ -150,7 +150,7 @@ bool cpuinfo_x86_decode_deterministic_cache_parameters(
bool cpuinfo_x86_decode_cache_properties(
struct cpuid_regs regs,
- struct cpuinfo_x86_caches cache[restrict static 1])
+ struct cpuinfo_x86_caches* cache)
{
const uint32_t type = regs.eax & UINT32_C(0x1F);
if (type == cache_type_none) {
diff --git a/src/x86/cache/init.c b/src/x86/cache/init.c
index 2e32e8a..b2af08d 100644
--- a/src/x86/cache/init.c
+++ b/src/x86/cache/init.c
@@ -23,22 +23,22 @@ void cpuinfo_x86_detect_cache(
uint32_t max_base_index, uint32_t max_extended_index,
bool amd_topology_extensions,
enum cpuinfo_vendor vendor,
- const struct cpuinfo_x86_model_info model_info[restrict static 1],
- struct cpuinfo_x86_caches cache[restrict static 1],
- struct cpuinfo_tlb itlb_4KB[restrict static 1],
- struct cpuinfo_tlb itlb_2MB[restrict static 1],
- struct cpuinfo_tlb itlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb0_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb0_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4KB[restrict static 1],
- struct cpuinfo_tlb dtlb_2MB[restrict static 1],
- struct cpuinfo_tlb dtlb_4MB[restrict static 1],
- struct cpuinfo_tlb dtlb_1GB[restrict static 1],
- struct cpuinfo_tlb stlb2_4KB[restrict static 1],
- struct cpuinfo_tlb stlb2_2MB[restrict static 1],
- struct cpuinfo_tlb stlb2_1GB[restrict static 1],
- uint32_t log2_package_cores_max[restrict static 1])
+ const struct cpuinfo_x86_model_info* model_info,
+ struct cpuinfo_x86_caches* cache,
+ struct cpuinfo_tlb* itlb_4KB,
+ struct cpuinfo_tlb* itlb_2MB,
+ struct cpuinfo_tlb* itlb_4MB,
+ struct cpuinfo_tlb* dtlb0_4KB,
+ struct cpuinfo_tlb* dtlb0_2MB,
+ struct cpuinfo_tlb* dtlb0_4MB,
+ struct cpuinfo_tlb* dtlb_4KB,
+ struct cpuinfo_tlb* dtlb_2MB,
+ struct cpuinfo_tlb* dtlb_4MB,
+ struct cpuinfo_tlb* dtlb_1GB,
+ struct cpuinfo_tlb* stlb2_4KB,
+ struct cpuinfo_tlb* stlb2_2MB,
+ struct cpuinfo_tlb* stlb2_1GB,
+ uint32_t* log2_package_cores_max)
{
if (max_base_index >= 2) {
union cpuinfo_x86_cache_descriptors descriptors;
diff --git a/src/x86/cpuid.h b/src/x86/cpuid.h
index f24fc98..829ec21 100644
--- a/src/x86/cpuid.h
+++ b/src/x86/cpuid.h
@@ -73,8 +73,12 @@
*/
#ifndef __native_client__
static inline uint64_t xgetbv(uint32_t ext_ctrl_reg) {
- uint32_t lo, hi;
- __asm__(".byte 0x0F, 0x01, 0xD0" : "=a" (lo), "=d" (hi) : "c" (ext_ctrl_reg));
- return ((uint64_t) hi << 32) | (uint64_t) lo;
+ #ifdef _MSC_VER
+ return (uint64_t)_xgetbv((unsigned int)ext_ctrl_reg);
+ #else
+ uint32_t lo, hi;
+ __asm__(".byte 0x0F, 0x01, 0xD0" : "=a" (lo), "=d" (hi) : "c" (ext_ctrl_reg));
+ return ((uint64_t) hi << 32) | (uint64_t) lo;
+ #endif
}
#endif
diff --git a/src/x86/init.c b/src/x86/init.c
index 3dcbb28..37f988d 100644
--- a/src/x86/init.c
+++ b/src/x86/init.c
@@ -11,7 +11,7 @@
struct cpuinfo_x86_isa cpuinfo_isa = { 0 };
uint32_t cpuinfo_x86_clflush_size = 0;
-void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor processor[restrict static 1]) {
+void cpuinfo_x86_init_processor(struct cpuinfo_x86_processor* processor) {
const struct cpuid_regs leaf0 = cpuid(0);
const uint32_t max_base_index = leaf0.eax;
const enum cpuinfo_vendor vendor = processor->vendor =
diff --git a/src/x86/isa.c b/src/x86/isa.c
index 3c1df0f..bca1ecd 100644
--- a/src/x86/isa.c
+++ b/src/x86/isa.c
@@ -7,6 +7,9 @@
#if CPUINFO_ARCH_X86
+ #ifdef _MSC_VER
+ #pragma pack(push, 2)
+ #endif
struct fxsave_region {
uint16_t fpu_control_word;
uint16_t fpu_status_word;
@@ -21,7 +24,14 @@
uint64_t fpu_registers[8 * 2];
uint64_t xmm_registers[8 * 2];
uint64_t padding[28];
- } __attribute__((__aligned__(16), __packed__));
+ }
+ #ifndef _MSC_VER
+ __attribute__((__aligned__(16), __packed__))
+ #endif
+ ; /* end of fxsave_region structure */
+ #ifdef _MSC_VER
+ #pragma pack(pop, 2)
+ #endif
#endif
@@ -298,7 +308,11 @@ struct cpuinfo_x86_isa cpuinfo_x86_detect_isa(
/* Detect DAZ support from masked MXCSR bits */
if (isa.sse && isa.fxsave) {
struct fxsave_region region = { 0 };
- __asm__ __volatile__ ("fxsave %[region];" : [region] "+m" (region));
+ #ifdef _MSC_VER
+ _fxsave(&region);
+ #else
+ __asm__ __volatile__ ("fxsave %[region];" : [region] "+m" (region));
+ #endif
/*
* Denormals-as-zero (DAZ) flag:
diff --git a/src/x86/linux/api.h b/src/x86/linux/api.h
index 33cd7f2..fc9f930 100644
--- a/src/x86/linux/api.h
+++ b/src/x86/linux/api.h
@@ -4,8 +4,7 @@
#include <stdint.h>
#include <cpuinfo.h>
-#include <arm/midr.h>
-#include <arm/api.h>
+#include <x86/api.h>
#include <linux/api.h>
diff --git a/src/x86/name.c b/src/x86/name.c
index 466601a..740c80c 100644
--- a/src/x86/name.c
+++ b/src/x86/name.c
@@ -47,7 +47,7 @@ struct parser_state {
};
/** @brief Resets information about the previous token. Keeps all other state information. */
-static void reset_context(struct parser_state state[restrict static 1]) {
+static void reset_context(struct parser_state* state) {
state->context_model = NULL;
state->context_upper_letter = NULL;
state->context_dual = NULL;
@@ -148,7 +148,7 @@ static inline char* move_token(const char* token_start, const char* token_end, c
return output_ptr + token_length;
}
-static bool transform_token(char* token_start, char* token_end, struct parser_state state[restrict static 1]) {
+static bool transform_token(char* token_start, char* token_end, struct parser_state* state) {
const struct parser_state previousState = *state;
reset_context(state);
@@ -521,8 +521,8 @@ static bool transform_token(char* token_start, char* token_end, struct parser_st
}
uint32_t cpuinfo_x86_normalize_brand_string(
- const char raw_name[restrict static 48],
- char normalized_name[restrict static 48])
+ const char raw_name[48],
+ char normalized_name[48])
{
normalized_name[0] = '\0';
char name[48];
diff --git a/src/x86/topology.c b/src/x86/topology.c
index b5e96fb..ece382b 100644
--- a/src/x86/topology.c
+++ b/src/x86/topology.c
@@ -18,7 +18,7 @@ void cpuinfo_x86_detect_topology(
uint32_t max_base_index,
uint32_t max_extended_index,
struct cpuid_regs leaf1,
- struct cpuinfo_x86_topology topology[restrict static 1])
+ struct cpuinfo_x86_topology* topology)
{
/*
* HTT: indicates multi-core/hyper-threading support on this core.
diff --git a/src/x86/uarch.c b/src/x86/uarch.c
index eb9035c..971b18c 100644
--- a/src/x86/uarch.c
+++ b/src/x86/uarch.c
@@ -6,7 +6,7 @@
enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
enum cpuinfo_vendor vendor,
- const struct cpuinfo_x86_model_info model_info[restrict static 1])
+ const struct cpuinfo_x86_model_info* model_info)
{
switch (vendor) {
case cpuinfo_vendor_intel:
diff --git a/src/x86/windows/api.h b/src/x86/windows/api.h
new file mode 100644
index 0000000..33d917e
--- /dev/null
+++ b/src/x86/windows/api.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <windows.h>
+
+#include <cpuinfo.h>
+#include <x86/api.h>
+
+struct cpuinfo_arm_linux_processor {
+ /**
+ * Minimum processor ID on the package which includes this logical processor.
+ * This value can serve as an ID for the cluster of logical processors: it is the
+ * same for all logical processors on the same package.
+ */
+ uint32_t package_leader_id;
+ /**
+ * Minimum processor ID on the core which includes this logical processor.
+ * This value can serve as an ID for the cluster of logical processors: it is the
+ * same for all logical processors on the same package.
+ */
+ /**
+ * Number of logical processors in the package.
+ */
+ uint32_t package_processor_count;
+ /**
+ * Maximum frequency, in kHZ.
+ * The value is parsed from /sys/devices/system/cpu/cpu<N>/cpufreq/cpuinfo_max_freq
+ * If failed to read or parse the file, the value is 0.
+ */
+ uint32_t max_frequency;
+ /**
+ * Minimum frequency, in kHZ.
+ * The value is parsed from /sys/devices/system/cpu/cpu<N>/cpufreq/cpuinfo_min_freq
+ * If failed to read or parse the file, the value is 0.
+ */
+ uint32_t min_frequency;
+ /** Linux processor ID */
+ uint32_t system_processor_id;
+ uint32_t flags;
+};
diff --git a/src/x86/windows/init.c b/src/x86/windows/init.c
new file mode 100644
index 0000000..6020bd5
--- /dev/null
+++ b/src/x86/windows/init.c
@@ -0,0 +1,573 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <cpuinfo.h>
+#include <x86/api.h>
+#include <api.h>
+#include <log.h>
+
+#include <Windows.h>
+
+static inline uint32_t bit_mask(uint32_t bits) {
+ return (UINT32_C(1) << bits) - UINT32_C(1);
+}
+
+static inline uint32_t low_index_from_kaffinity(KAFFINITY kaffinity) {
+ #if defined(_M_X64) || defined(_M_AMD64)
+ unsigned long index;
+ _BitScanForward64(&index, (unsigned __int64) kaffinity);
+ return (uint32_t) index;
+ #elif defined(_M_IX86)
+ unsigned long index;
+ _BitScanForward(&index, (unsigned long) kaffinity);
+ return (uint32_t) index;
+ #else
+ #error Platform-specific implementation required
+ #endif
+}
+
+static void cpuinfo_x86_count_caches(
+ uint32_t processors_count,
+ const struct cpuinfo_processor* processors,
+ const struct cpuinfo_x86_processor* x86_processor,
+ uint32_t* l1i_count_ptr,
+ uint32_t* l1d_count_ptr,
+ uint32_t* l2_count_ptr,
+ uint32_t* l3_count_ptr,
+ uint32_t* l4_count_ptr)
+{
+ uint32_t l1i_count = 0, l1d_count = 0, l2_count = 0, l3_count = 0, l4_count = 0;
+ uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX;
+ uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX;
+ for (uint32_t i = 0; i < processors_count; i++) {
+ const uint32_t apic_id = processors[i].apic_id;
+ cpuinfo_log_debug("APID ID %"PRIu32": logical processor %"PRIu32, apic_id, i);
+
+ if (x86_processor->cache.l1i.size != 0) {
+ const uint32_t l1i_id = apic_id & ~bit_mask(x86_processor->cache.l1i.apic_bits);
+ if (l1i_id != last_l1i_id) {
+ last_l1i_id = l1i_id;
+ l1i_count++;
+ }
+ }
+ if (x86_processor->cache.l1d.size != 0) {
+ const uint32_t l1d_id = apic_id & ~bit_mask(x86_processor->cache.l1d.apic_bits);
+ if (l1d_id != last_l1d_id) {
+ last_l1d_id = l1d_id;
+ l1d_count++;
+ }
+ }
+ if (x86_processor->cache.l2.size != 0) {
+ const uint32_t l2_id = apic_id & ~bit_mask(x86_processor->cache.l2.apic_bits);
+ if (l2_id != last_l2_id) {
+ last_l2_id = l2_id;
+ l2_count++;
+ }
+ }
+ if (x86_processor->cache.l3.size != 0) {
+ const uint32_t l3_id = apic_id & ~bit_mask(x86_processor->cache.l3.apic_bits);
+ if (l3_id != last_l3_id) {
+ last_l3_id = l3_id;
+ l3_count++;
+ }
+ }
+ if (x86_processor->cache.l4.size != 0) {
+ const uint32_t l4_id = apic_id & ~bit_mask(x86_processor->cache.l4.apic_bits);
+ if (l4_id != last_l4_id) {
+ last_l4_id = l4_id;
+ l4_count++;
+ }
+ }
+ }
+ *l1i_count_ptr = l1i_count;
+ *l1d_count_ptr = l1d_count;
+ *l2_count_ptr = l2_count;
+ *l3_count_ptr = l3_count;
+ *l4_count_ptr = l4_count;
+}
+
+BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context) {
+ struct cpuinfo_processor* processors = NULL;
+ struct cpuinfo_core* cores = NULL;
+ struct cpuinfo_package* packages = NULL;
+ struct cpuinfo_cache* l1i = NULL;
+ struct cpuinfo_cache* l1d = NULL;
+ struct cpuinfo_cache* l2 = NULL;
+ struct cpuinfo_cache* l3 = NULL;
+ struct cpuinfo_cache* l4 = NULL;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX processor_infos = NULL;
+
+ HANDLE heap = GetProcessHeap();
+
+ struct cpuinfo_x86_processor x86_processor;
+ ZeroMemory(&x86_processor, sizeof(x86_processor));
+ cpuinfo_x86_init_processor(&x86_processor);
+
+ const uint32_t thread_bits_mask = bit_mask(x86_processor.topology.thread_bits_length);
+ const uint32_t core_bits_mask = bit_mask(x86_processor.topology.core_bits_length);
+ const uint32_t package_bits_offset = max(
+ x86_processor.topology.thread_bits_offset + x86_processor.topology.thread_bits_length,
+ x86_processor.topology.core_bits_offset + x86_processor.topology.core_bits_length);
+
+ const uint32_t max_group_count = (uint32_t) GetMaximumProcessorGroupCount();
+ cpuinfo_log_debug("detected %"PRIu32" processor groups", max_group_count);
+
+ uint32_t processors_count = 0;
+ uint32_t* processors_per_group = (uint32_t*) _alloca(max_group_count * sizeof(uint32_t));
+ for (uint32_t i = 0; i < max_group_count; i++) {
+ processors_per_group[i] = GetMaximumProcessorCount((WORD) i);
+ cpuinfo_log_debug("detected %"PRIu32" processors in group %"PRIu32,
+ processors_per_group[i], i);
+ processors_count += processors_per_group[i];
+ }
+
+ uint32_t* processors_before_group = (uint32_t*) _alloca(max_group_count * sizeof(uint32_t));
+ for (uint32_t i = 0, count = 0; i < max_group_count; i++) {
+ processors_before_group[i] = count;
+ cpuinfo_log_debug("detected %"PRIu32" processors before group %"PRIu32,
+ processors_before_group[i], i);
+ count += processors_per_group[i];
+ }
+
+ processors = HeapAlloc(heap, HEAP_ZERO_MEMORY, processors_count * sizeof(struct cpuinfo_processor));
+ if (processors == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" logical processors",
+ processors_count * sizeof(struct cpuinfo_processor), processors_count);
+ goto cleanup;
+ }
+
+ DWORD cores_info_size = 0;
+ if (GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &cores_info_size) == FALSE) {
+ const DWORD last_error = GetLastError();
+ if (last_error != ERROR_INSUFFICIENT_BUFFER) {
+ cpuinfo_log_error("failed to query size of processor cores information: error %"PRIu32,
+ (uint32_t) last_error);
+ goto cleanup;
+ }
+ }
+
+ DWORD packages_info_size = 0;
+ if (GetLogicalProcessorInformationEx(RelationProcessorPackage, NULL, &packages_info_size) == FALSE) {
+ const DWORD last_error = GetLastError();
+ if (last_error != ERROR_INSUFFICIENT_BUFFER) {
+ cpuinfo_log_error("failed to query size of processor packages information: error %"PRIu32,
+ (uint32_t) last_error);
+ goto cleanup;
+ }
+ }
+
+ DWORD max_info_size = max(cores_info_size, packages_info_size);
+
+ processor_infos = HeapAlloc(heap, 0, max_info_size);
+ if (processor_infos == NULL) {
+ cpuinfo_log_error("failed to allocate %"PRIu32" bytes for logical processor information",
+ (uint32_t) max_info_size);
+ goto cleanup;
+ }
+
+ if (GetLogicalProcessorInformationEx(RelationProcessorPackage, processor_infos, &max_info_size) == FALSE) {
+ cpuinfo_log_error("failed to query processor packages information: error %"PRIu32,
+ (uint32_t) GetLastError());
+ goto cleanup;
+ }
+
+ uint32_t packages_count = 0;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX packages_info_end =
+ (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ((uintptr_t) processor_infos + packages_info_size);
+ for (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX package_info = processor_infos;
+ package_info < packages_info_end;
+ package_info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ((uintptr_t) package_info + package_info->Size))
+ {
+ if (package_info->Relationship != RelationProcessorPackage) {
+ cpuinfo_log_warning("unexpected processor info type (%"PRIu32") for processor package information",
+ (uint32_t) package_info->Relationship);
+ continue;
+ }
+
+ /* We assume that packages are reported in APIC order */
+ const uint32_t package_id = packages_count++;
+ /* Reconstruct package part of APIC ID */
+ const uint32_t package_apic_id = package_id << package_bits_offset;
+ /* Iterate processor groups and set the package part of APIC ID */
+ for (uint32_t i = 0; i < package_info->Processor.GroupCount; i++) {
+ const uint32_t group_id = package_info->Processor.GroupMask[i].Group;
+ /* Global index of the first logical processor belonging to this group */
+ const uint32_t group_processors_start = processors_before_group[group_id];
+ /* Bitmask representing processors in this group belonging to this package */
+ KAFFINITY group_processors_mask = package_info->Processor.GroupMask[i].Mask;
+ while (group_processors_mask != 0) {
+ const uint32_t group_processor_id = low_index_from_kaffinity(group_processors_mask);
+ const uint32_t processor_id = group_processors_start + group_processor_id;
+ processors[processor_id].package = (const struct cpuinfo_package*) NULL + package_id;
+ processors[processor_id].windows_group_id = (uint16_t) group_id;
+ processors[processor_id].windows_processor_id = (uint16_t) group_processor_id;
+ processors[processor_id].apic_id = package_apic_id;
+
+ /* Reset the lowest bit in affinity mask */
+ group_processors_mask &= (group_processors_mask - 1);
+ }
+ }
+ }
+
+ max_info_size = max(cores_info_size, packages_info_size);
+ if (GetLogicalProcessorInformationEx(RelationProcessorCore, processor_infos, &max_info_size) == FALSE) {
+ cpuinfo_log_error("failed to query processor cores information: error %"PRIu32,
+ (uint32_t) GetLastError());
+ goto cleanup;
+ }
+
+ uint32_t cores_count = 0;
+ /* Index (among all cores) of the the first core on the current package */
+ uint32_t package_core_start = 0;
+ uint32_t current_package_apic_id = 0;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX cores_info_end =
+ (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ((uintptr_t) processor_infos + cores_info_size);
+ for (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX core_info = processor_infos;
+ core_info < cores_info_end;
+ core_info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) ((uintptr_t) core_info + core_info->Size))
+ {
+ if (core_info->Relationship != RelationProcessorCore) {
+ cpuinfo_log_warning("unexpected processor info type (%"PRIu32") for processor core information",
+ (uint32_t) core_info->Relationship);
+ continue;
+ }
+
+ /* We assume that cores and logical processors are reported in APIC order */
+ const uint32_t core_id = cores_count++;
+ uint32_t smt_id = 0;
+ /* Reconstruct core part of APIC ID */
+ const uint32_t core_apic_id = (core_id & core_bits_mask) << x86_processor.topology.core_bits_offset;
+ /* Iterate processor groups and set the core & SMT parts of APIC ID */
+ for (uint32_t i = 0; i < core_info->Processor.GroupCount; i++) {
+ const uint32_t group_id = core_info->Processor.GroupMask[i].Group;
+ /* Global index of the first logical processor belonging to this group */
+ const uint32_t group_processors_start = processors_before_group[group_id];
+ /* Bitmask representing processors in this group belonging to this package */
+ KAFFINITY group_processors_mask = core_info->Processor.GroupMask[i].Mask;
+ while (group_processors_mask != 0) {
+ const uint32_t group_processor_id = low_index_from_kaffinity(group_processors_mask);
+ const uint32_t processor_id = group_processors_start + group_processor_id;
+
+ /* Check if this is the first core on a new package */
+ if (processors[processor_id].apic_id != current_package_apic_id) {
+ package_core_start = core_id;
+ current_package_apic_id = processors[processor_id].apic_id;
+ }
+ /* Core ID w.r.t package */
+ const uint32_t package_core_id = core_id - package_core_start;
+
+ /* Update APIC ID with core and SMT parts */
+ processors[processor_id].apic_id |=
+ ((smt_id & thread_bits_mask) << x86_processor.topology.thread_bits_offset) |
+ ((package_core_id & core_bits_mask) << x86_processor.topology.core_bits_offset);
+ cpuinfo_log_debug("reconstructed APIC ID 0x%08"PRIx32" for processor %"PRIu32" in group %"PRIu32,
+ processors[processor_id].apic_id, group_processor_id, group_id);
+
+ /* Set SMT ID (assume logical processors within the core are reported in APIC order) */
+ processors[processor_id].smt_id = smt_id++;
+ processors[processor_id].core = (const struct cpuinfo_core*) NULL + core_id;
+
+ /* Reset the lowest bit in affinity mask */
+ group_processors_mask &= (group_processors_mask - 1);
+ }
+ }
+ }
+
+ cores = HeapAlloc(heap, HEAP_ZERO_MEMORY, cores_count * sizeof(struct cpuinfo_core));
+ if (cores == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" cores",
+ cores_count * sizeof(struct cpuinfo_core), cores_count);
+ goto cleanup;
+ }
+
+ packages = HeapAlloc(heap, HEAP_ZERO_MEMORY, packages_count * sizeof(struct cpuinfo_package));
+ if (packages == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" packages",
+ packages_count * sizeof(struct cpuinfo_package), packages_count);
+ goto cleanup;
+ }
+
+ for (uint32_t i = processors_count; i != 0; i--) {
+ const uint32_t processor_id = i - 1;
+ struct cpuinfo_processor* processor = processors + processor_id;
+
+ /* Adjust core and package pointers for all logical processors */
+ struct cpuinfo_core* core =
+ (struct cpuinfo_core*) ((uintptr_t) cores + (uintptr_t) processor->core);
+ processor->core = core;
+ struct cpuinfo_package* package =
+ (struct cpuinfo_package*) ((uintptr_t)packages + (uintptr_t)processor->package);
+ processor->package = package;
+
+ /* This can be overwritten by lower-index processors on the same package */
+ package->processor_start = processor_id;
+ package->processor_count += 1;
+
+ /* This can be overwritten by lower-index processors on the same core*/
+ core->processor_start = processor_id;
+ core->processor_count += 1;
+ }
+
+ /* Set vendor/uarch/CPUID information for cores */
+ for (uint32_t i = cores_count; i != 0; i--) {
+ const uint32_t global_core_id = i - 1;
+ struct cpuinfo_core* core = cores + global_core_id;
+ const struct cpuinfo_processor* processor = processors + core->processor_start;
+ struct cpuinfo_package* package = (struct cpuinfo_package*) processor->package;
+
+ core->package = package;
+ core->core_id = core_bits_mask &
+ (processor->apic_id >> x86_processor.topology.core_bits_offset);
+ core->vendor = x86_processor.vendor;
+ core->uarch = x86_processor.uarch;
+ core->cpuid = x86_processor.cpuid;
+
+ /* This can be overwritten by lower-index cores on the same package */
+ package->core_start = global_core_id;
+ package->core_count += 1;
+ }
+
+ for (uint32_t i = 0; i < packages_count; i++) {
+ cpuinfo_x86_normalize_brand_string(x86_processor.brand_string, packages[i].name);
+ }
+
+ /* Count caches */
+ uint32_t l1i_count, l1d_count, l2_count, l3_count, l4_count;
+ cpuinfo_x86_count_caches(processors_count, processors, &x86_processor,
+ &l1i_count, &l1d_count, &l2_count, &l3_count, &l4_count);
+
+ /* Allocate cache descriptions */
+ if (l1i_count != 0) {
+ l1i = HeapAlloc(heap, HEAP_ZERO_MEMORY, l1i_count * sizeof(struct cpuinfo_cache));
+ if (l1i == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1I caches",
+ l1i_count * sizeof(struct cpuinfo_cache), l1i_count);
+ goto cleanup;
+ }
+ }
+ if (l1d_count != 0) {
+ l1d = HeapAlloc(heap, HEAP_ZERO_MEMORY, l1d_count * sizeof(struct cpuinfo_cache));
+ if (l1d == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L1D caches",
+ l1d_count * sizeof(struct cpuinfo_cache), l1d_count);
+ goto cleanup;
+ }
+ }
+ if (l2_count != 0) {
+ l2 = HeapAlloc(heap, HEAP_ZERO_MEMORY, l2_count * sizeof(struct cpuinfo_cache));
+ if (l2 == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L2 caches",
+ l2_count * sizeof(struct cpuinfo_cache), l2_count);
+ goto cleanup;
+ }
+ }
+ if (l3_count != 0) {
+ l3 = HeapAlloc(heap, HEAP_ZERO_MEMORY, l3_count * sizeof(struct cpuinfo_cache));
+ if (l3 == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L3 caches",
+ l3_count * sizeof(struct cpuinfo_cache), l3_count);
+ goto cleanup;
+ }
+ }
+ if (l4_count != 0) {
+ l4 = HeapAlloc(heap, HEAP_ZERO_MEMORY, l4_count * sizeof(struct cpuinfo_cache));
+ if (l4 == NULL) {
+ cpuinfo_log_error("failed to allocate %zu bytes for descriptions of %"PRIu32" L4 caches",
+ l4_count * sizeof(struct cpuinfo_cache), l4_count);
+ goto cleanup;
+ }
+ }
+
+ /* Set cache information */
+ uint32_t l1i_index = UINT32_MAX, l1d_index = UINT32_MAX, l2_index = UINT32_MAX, l3_index = UINT32_MAX, l4_index = UINT32_MAX;
+ uint32_t last_l1i_id = UINT32_MAX, last_l1d_id = UINT32_MAX;
+ uint32_t last_l2_id = UINT32_MAX, last_l3_id = UINT32_MAX, last_l4_id = UINT32_MAX;
+ for (uint32_t i = 0; i < processors_count; i++) {
+ const uint32_t apic_id = processors[i].apic_id;
+
+ //linux_cpu_to_processor_map[x86_linux_processors[i].linux_id] = processors + processor_index;
+ //linux_cpu_to_core_map[x86_linux_processors[i].linux_id] = cores + core_index;
+
+ if (x86_processor.cache.l1i.size != 0) {
+ const uint32_t l1i_id = apic_id & ~bit_mask(x86_processor.cache.l1i.apic_bits);
+ processors[i].cache.l1i = &l1i[l1i_index];
+ if (l1i_id != last_l1i_id) {
+ /* new cache */
+ last_l1i_id = l1i_id;
+ l1i[++l1i_index] = (struct cpuinfo_cache) {
+ .size = x86_processor.cache.l1i.size,
+ .associativity = x86_processor.cache.l1i.associativity,
+ .sets = x86_processor.cache.l1i.sets,
+ .partitions = x86_processor.cache.l1i.partitions,
+ .line_size = x86_processor.cache.l1i.line_size,
+ .flags = x86_processor.cache.l1i.flags,
+ .processor_start = i,
+ .processor_count = 1,
+ };
+ } else {
+ /* another processor sharing the same cache */
+ l1i[l1i_index].processor_count += 1;
+ }
+ processors[i].cache.l1i = &l1i[l1i_index];
+ } else {
+ /* reset cache id */
+ last_l1i_id = UINT32_MAX;
+ }
+ if (x86_processor.cache.l1d.size != 0) {
+ const uint32_t l1d_id = apic_id & ~bit_mask(x86_processor.cache.l1d.apic_bits);
+ processors[i].cache.l1d = &l1d[l1d_index];
+ if (l1d_id != last_l1d_id) {
+ /* new cache */
+ last_l1d_id = l1d_id;
+ l1d[++l1d_index] = (struct cpuinfo_cache) {
+ .size = x86_processor.cache.l1d.size,
+ .associativity = x86_processor.cache.l1d.associativity,
+ .sets = x86_processor.cache.l1d.sets,
+ .partitions = x86_processor.cache.l1d.partitions,
+ .line_size = x86_processor.cache.l1d.line_size,
+ .flags = x86_processor.cache.l1d.flags,
+ .processor_start = i,
+ .processor_count = 1,
+ };
+ } else {
+ /* another processor sharing the same cache */
+ l1d[l1d_index].processor_count += 1;
+ }
+ processors[i].cache.l1d = &l1d[l1d_index];
+ } else {
+ /* reset cache id */
+ last_l1d_id = UINT32_MAX;
+ }
+ if (x86_processor.cache.l2.size != 0) {
+ const uint32_t l2_id = apic_id & ~bit_mask(x86_processor.cache.l2.apic_bits);
+ processors[i].cache.l2 = &l2[l2_index];
+ if (l2_id != last_l2_id) {
+ /* new cache */
+ last_l2_id = l2_id;
+ l2[++l2_index] = (struct cpuinfo_cache) {
+ .size = x86_processor.cache.l2.size,
+ .associativity = x86_processor.cache.l2.associativity,
+ .sets = x86_processor.cache.l2.sets,
+ .partitions = x86_processor.cache.l2.partitions,
+ .line_size = x86_processor.cache.l2.line_size,
+ .flags = x86_processor.cache.l2.flags,
+ .processor_start = i,
+ .processor_count = 1,
+ };
+ } else {
+ /* another processor sharing the same cache */
+ l2[l2_index].processor_count += 1;
+ }
+ processors[i].cache.l2 = &l2[l2_index];
+ } else {
+ /* reset cache id */
+ last_l2_id = UINT32_MAX;
+ }
+ if (x86_processor.cache.l3.size != 0) {
+ const uint32_t l3_id = apic_id & ~bit_mask(x86_processor.cache.l3.apic_bits);
+ processors[i].cache.l3 = &l3[l3_index];
+ if (l3_id != last_l3_id) {
+ /* new cache */
+ last_l3_id = l3_id;
+ l3[++l3_index] = (struct cpuinfo_cache) {
+ .size = x86_processor.cache.l3.size,
+ .associativity = x86_processor.cache.l3.associativity,
+ .sets = x86_processor.cache.l3.sets,
+ .partitions = x86_processor.cache.l3.partitions,
+ .line_size = x86_processor.cache.l3.line_size,
+ .flags = x86_processor.cache.l3.flags,
+ .processor_start = i,
+ .processor_count = 1,
+ };
+ } else {
+ /* another processor sharing the same cache */
+ l3[l3_index].processor_count += 1;
+ }
+ processors[i].cache.l3 = &l3[l3_index];
+ } else {
+ /* reset cache id */
+ last_l3_id = UINT32_MAX;
+ }
+ if (x86_processor.cache.l4.size != 0) {
+ const uint32_t l4_id = apic_id & ~bit_mask(x86_processor.cache.l4.apic_bits);
+ processors[i].cache.l4 = &l4[l4_index];
+ if (l4_id != last_l4_id) {
+ /* new cache */
+ last_l4_id = l4_id;
+ l4[++l4_index] = (struct cpuinfo_cache) {
+ .size = x86_processor.cache.l4.size,
+ .associativity = x86_processor.cache.l4.associativity,
+ .sets = x86_processor.cache.l4.sets,
+ .partitions = x86_processor.cache.l4.partitions,
+ .line_size = x86_processor.cache.l4.line_size,
+ .flags = x86_processor.cache.l4.flags,
+ .processor_start = i,
+ .processor_count = 1,
+ };
+ } else {
+ /* another processor sharing the same cache */
+ l4[l4_index].processor_count += 1;
+ }
+ processors[i].cache.l4 = &l4[l4_index];
+ } else {
+ /* reset cache id */
+ last_l4_id = UINT32_MAX;
+ }
+ }
+
+
+ /* Commit changes */
+ cpuinfo_cache[cpuinfo_cache_level_1i] = l1i;
+ cpuinfo_cache[cpuinfo_cache_level_1d] = l1d;
+ cpuinfo_cache[cpuinfo_cache_level_2] = l2;
+ cpuinfo_cache[cpuinfo_cache_level_3] = l3;
+ cpuinfo_cache[cpuinfo_cache_level_4] = l4;
+
+ cpuinfo_processors = processors;
+ cpuinfo_cores = cores;
+ cpuinfo_packages = packages;
+
+ cpuinfo_cache_count[cpuinfo_cache_level_1i] = l1i_count;
+ cpuinfo_cache_count[cpuinfo_cache_level_1d] = l1d_count;
+ cpuinfo_cache_count[cpuinfo_cache_level_2] = l2_count;
+ cpuinfo_cache_count[cpuinfo_cache_level_3] = l3_count;
+ cpuinfo_cache_count[cpuinfo_cache_level_4] = l4_count;
+
+ cpuinfo_processors_count = processors_count;
+ cpuinfo_cores_count = cores_count;
+ cpuinfo_packages_count = packages_count;
+
+ processors = NULL;
+ cores = NULL;
+ packages = NULL;
+ l1i = l1d = l2 = l3 = l4 = NULL;
+
+cleanup:
+ if (processors != NULL) {
+ HeapFree(heap, 0, processors);
+ }
+ if (cores != NULL) {
+ HeapFree(heap, 0, cores);
+ }
+ if (packages != NULL) {
+ HeapFree(heap, 0, packages);
+ }
+ if (l1i != NULL) {
+ HeapFree(heap, 0, l1i);
+ }
+ if (l1d != NULL) {
+ HeapFree(heap, 0, l1d);
+ }
+ if (l2 != NULL) {
+ HeapFree(heap, 0, l2);
+ }
+ if (l3 != NULL) {
+ HeapFree(heap, 0, l3);
+ }
+ if (l4 != NULL) {
+ HeapFree(heap, 0, l4);
+ }
+ return TRUE;
+}
diff --git a/tools/cache-info.c b/tools/cache-info.c
index cbe9e6e..a4ca3e8 100644
--- a/tools/cache-info.c
+++ b/tools/cache-info.c
@@ -5,7 +5,7 @@
void report_cache(
- uint32_t count, const struct cpuinfo_cache cache[restrict static 1],
+ uint32_t count, const struct cpuinfo_cache* cache,
uint32_t level, const char* nonunified_type)
{
const char* type = (cache->flags & CPUINFO_CACHE_UNIFIED) ? "unified" : nonunified_type;
diff --git a/tools/cpu-info.c b/tools/cpu-info.c
index 5d4002f..445b433 100644
--- a/tools/cpu-info.c
+++ b/tools/cpu-info.c
@@ -196,25 +196,32 @@ int main(int argc, char** argv) {
for (uint32_t i = 0; i < cpuinfo_get_cores_count(); i++) {
const struct cpuinfo_core* core = cpuinfo_get_core(i);
if (core->processor_count == 1) {
- printf("\t%"PRIu32": 1 processor (%"PRIu32")\n", i, core->processor_start);
+ printf("\t%"PRIu32": 1 processor (%"PRIu32")", i, core->processor_start);
} else {
- printf("\t%"PRIu32": %"PRIu32" processors (%"PRIu32"-%"PRIu32")\n",
+ printf("\t%"PRIu32": %"PRIu32" processors (%"PRIu32"-%"PRIu32")",
i, core->processor_count, core->processor_start, core->processor_start + core->processor_count - 1);
}
+ const char* vendor_string = vendor_to_string(core->vendor);
+ const char* uarch_string = uarch_to_string(core->uarch);
+ if (vendor_string == NULL) {
+ printf(", vendor 0x%08"PRIx32" uarch 0x%08"PRIx32"\n",
+ (uint32_t) core->vendor, (uint32_t) core->uarch);
+ }
+ else if (uarch_string == NULL) {
+ printf(", %s uarch 0x%08"PRIx32"\n",
+ vendor_string, (uint32_t) core->uarch);
+ }
+ else {
+ printf(", %s %s\n", vendor_string, uarch_string);
+ }
}
printf("Logical processors:\n");
for (uint32_t i = 0; i < cpuinfo_get_processors_count(); i++) {
const struct cpuinfo_processor* processor = cpuinfo_get_processor(i);
- const char* vendor_string = vendor_to_string(processor->core->vendor);
- const char* uarch_string = uarch_to_string(processor->core->uarch);
- if (vendor_string == NULL) {
- printf("\t%"PRIu32": vendor 0x%08"PRIx32" uarch 0x%08"PRIx32"\n",
- i, (uint32_t) processor->core->vendor, (uint32_t) processor->core->uarch);
- } else if (uarch_string == NULL) {
- printf("\t%"PRIu32": %s uarch 0x%08"PRIx32"\n",
- i, vendor_string, (uint32_t) processor->core->uarch);
- } else {
- printf("\t%"PRIu32": %s %s\n", i, vendor_string, uarch_string);
- }
+ #if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
+ printf("\t%"PRIu32": APIC ID 0x%08"PRIx32"\n", i, processor->apic_id);
+ #else
+ printf("\t%"PRIu32"\n", i);
+ #endif
}
}