diff options
author | Marat Dukhan <maratek@gmail.com> | 2018-02-19 22:43:26 -0800 |
---|---|---|
committer | Marat Dukhan <maratek@gmail.com> | 2018-02-19 22:48:12 -0800 |
commit | b2fc4ab8099b802de934f24adf2da6e4c863bd3c (patch) | |
tree | e2e22022cc4d4d1de9eba0e6628f127e7e8806ee | |
parent | a9e55a6afde89722af7ee30dc7bd27435e96226b (diff) | |
download | cpuinfo-b2fc4ab8099b802de934f24adf2da6e4c863bd3c.tar.gz |
Windows support
-rw-r--r-- | CMakeLists.txt | 8 | ||||
-rw-r--r-- | include/cpuinfo.h | 9 | ||||
-rw-r--r-- | src/api.h | 7 | ||||
-rw-r--r-- | src/init.c | 14 | ||||
-rw-r--r-- | src/log.c | 12 | ||||
-rw-r--r-- | src/utils.h | 8 | ||||
-rw-r--r-- | src/x86/api.h | 80 | ||||
-rw-r--r-- | src/x86/cache/descriptor.c | 32 | ||||
-rw-r--r-- | src/x86/cache/deterministic.c | 6 | ||||
-rw-r--r-- | src/x86/cache/init.c | 32 | ||||
-rw-r--r-- | src/x86/cpuid.h | 10 | ||||
-rw-r--r-- | src/x86/init.c | 2 | ||||
-rw-r--r-- | src/x86/isa.c | 18 | ||||
-rw-r--r-- | src/x86/linux/api.h | 3 | ||||
-rw-r--r-- | src/x86/name.c | 8 | ||||
-rw-r--r-- | src/x86/topology.c | 2 | ||||
-rw-r--r-- | src/x86/uarch.c | 2 | ||||
-rw-r--r-- | src/x86/windows/api.h | 41 | ||||
-rw-r--r-- | src/x86/windows/init.c | 573 | ||||
-rw-r--r-- | tools/cache-info.c | 2 | ||||
-rw-r--r-- | tools/cpu-info.c | 33 |
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; @@ -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); @@ -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 @@ -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(®ion); + #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 } } |