- refactor for auto detection
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bd9f77f..aedc983 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -187,7 +187,8 @@
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^Windows" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(ARM64|arm64)$")
LIST(APPEND CPUINFO_SRCS
src/arm/windows/init-by-logical-sys-info.c
- src/arm/windows/init.c)
+ src/arm/windows/init.c
+ src/arm/uarch.c)
ELSEIF(CPUINFO_TARGET_PROCESSOR MATCHES "^(armv[5-8].*|aarch64|arm64.*)$" OR IOS_ARCH MATCHES "^(armv7.*|arm64.*)$")
LIST(APPEND CPUINFO_SRCS
src/arm/uarch.c
diff --git a/include/cpuinfo.h b/include/cpuinfo.h
index ea3c1d0..5f93819 100644
--- a/include/cpuinfo.h
+++ b/include/cpuinfo.h
@@ -522,6 +522,8 @@
cpuinfo_uarch_falkor = 0x00400103,
/** Qualcomm Saphira. */
cpuinfo_uarch_saphira = 0x00400104,
+ /** Qualcomm Oryon. */
+ cpuinfo_uarch_oryon = 0x00400105,
/** Nvidia Denver. */
cpuinfo_uarch_denver = 0x00500100,
diff --git a/src/arm/api.h b/src/arm/api.h
index ac735e3..b1be639 100644
--- a/src/arm/api.h
+++ b/src/arm/api.h
@@ -1,5 +1,11 @@
#pragma once
+#ifdef _MSC_VER
+ #define RESTRICT_STATIC /* nothing for MSVC */
+#else
+ #define RESTRICT_STATIC restrict static
+#endif
+
#include <stdbool.h>
#include <stdint.h>
@@ -82,11 +88,11 @@
#ifndef __cplusplus
CPUINFO_INTERNAL void cpuinfo_arm_chipset_to_string(
- const struct cpuinfo_arm_chipset chipset[restrict static 1],
- char name[restrict static CPUINFO_ARM_CHIPSET_NAME_MAX]);
+ const struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
+ char name[RESTRICT_STATIC CPUINFO_ARM_CHIPSET_NAME_MAX]);
CPUINFO_INTERNAL void cpuinfo_arm_fixup_chipset(
- struct cpuinfo_arm_chipset chipset[restrict static 1],
+ struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
uint32_t cores,
uint32_t max_cpu_freq_max);
@@ -95,23 +101,23 @@
#if CPUINFO_ARCH_ARM
bool has_vfpv4,
#endif
- enum cpuinfo_vendor vendor[restrict static 1],
- enum cpuinfo_uarch uarch[restrict static 1]);
+ enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
+ enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]);
CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
enum cpuinfo_uarch uarch,
uint32_t cluster_cores,
uint32_t midr,
- const struct cpuinfo_arm_chipset chipset[restrict static 1],
+ const struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
uint32_t cluster_id,
uint32_t arch_version,
- struct cpuinfo_cache l1i[restrict static 1],
- struct cpuinfo_cache l1d[restrict static 1],
- struct cpuinfo_cache l2[restrict static 1],
- struct cpuinfo_cache l3[restrict static 1]);
+ struct cpuinfo_cache l1i[RESTRICT_STATIC 1],
+ struct cpuinfo_cache l1d[RESTRICT_STATIC 1],
+ struct cpuinfo_cache l2[RESTRICT_STATIC 1],
+ struct cpuinfo_cache l3[RESTRICT_STATIC 1]);
CPUINFO_INTERNAL uint32_t
-cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor processor[restrict static 1]);
+cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor processor[RESTRICT_STATIC 1]);
#else /* defined(__cplusplus) */
CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
enum cpuinfo_uarch uarch,
diff --git a/src/arm/uarch.c b/src/arm/uarch.c
index 68531e4..9679f50 100644
--- a/src/arm/uarch.c
+++ b/src/arm/uarch.c
@@ -9,8 +9,8 @@
#if CPUINFO_ARCH_ARM
bool has_vfpv4,
#endif /* CPUINFO_ARCH_ARM */
- enum cpuinfo_vendor vendor[restrict static 1],
- enum cpuinfo_uarch uarch[restrict static 1]) {
+ enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
+ enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]) {
switch (midr_get_implementer(midr)) {
case 'A':
*vendor = cpuinfo_vendor_arm;
@@ -332,6 +332,9 @@
*uarch = cpuinfo_uarch_cortex_a55;
break;
#if CPUINFO_ARCH_ARM64
+ case 0x001:
+ *uarch = cpuinfo_uarch_oryon;
+ break;
case 0xC00:
*uarch = cpuinfo_uarch_falkor;
break;
diff --git a/src/arm/windows/init-by-logical-sys-info.c b/src/arm/windows/init-by-logical-sys-info.c
index 6ce6efe..ecb238e 100644
--- a/src/arm/windows/init-by-logical-sys-info.c
+++ b/src/arm/windows/init-by-logical-sys-info.c
@@ -750,11 +750,14 @@
if (cores) {
processors[processor_global_index].core = cores + core_id;
cores[core_id].core_id = core_id;
- get_core_uarch_for_efficiency(
- chip_info->chip_name,
- core_info->Processor.EfficiencyClass,
- &(cores[core_id].uarch),
- &(cores[core_id].frequency));
+
+ if (chip_info->uarchs == NULL) {
+ cpuinfo_log_error("uarch is NULL for core %d", core_id);
+ return;
+ }
+
+ cores[core_id].uarch = chip_info->uarchs[0].uarch;
+ cores[core_id].frequency = chip_info->uarchs[0].frequency;
/* We don't have cluster information, so we handle it as
* fixed 1 to (cluster / cores).
diff --git a/src/arm/windows/init.c b/src/arm/windows/init.c
index de2f6cc..8409843 100644
--- a/src/arm/windows/init.c
+++ b/src/arm/windows/init.c
@@ -7,6 +7,9 @@
#include <cpuinfo/internal-api.h>
#include <cpuinfo/log.h>
+#include <arm/api.h>
+#include <arm/midr.h>
+
#include "windows-arm-init.h"
struct cpuinfo_arm_isa cpuinfo_isa;
@@ -14,62 +17,7 @@
static void set_cpuinfo_isa_fields(void);
static struct woa_chip_info* get_system_info_from_registry(void);
-static struct woa_chip_info woa_chip_unknown = {
- L"Unknown",
- woa_chip_name_unknown,
- {{cpuinfo_vendor_unknown, cpuinfo_uarch_unknown, 0}}};
-
-/* Please add new SoC/chip info here! */
-static struct woa_chip_info woa_chips[woa_chip_name_last] = {
- /* Microsoft SQ1 Kryo 495 4 + 4 cores (3 GHz + 1.80 GHz) */
- [woa_chip_name_microsoft_sq_1] =
- {L"Microsoft SQ1",
- woa_chip_name_microsoft_sq_1,
- {{
- cpuinfo_vendor_arm,
- cpuinfo_uarch_cortex_a55,
- 1800000000,
- },
- {
- cpuinfo_vendor_arm,
- cpuinfo_uarch_cortex_a76,
- 3000000000,
- }}},
- /* Microsoft SQ2 Kryo 495 4 + 4 cores (3.15 GHz + 2.42 GHz) */
- [woa_chip_name_microsoft_sq_2] =
- {L"Microsoft SQ2",
- woa_chip_name_microsoft_sq_2,
- {{
- cpuinfo_vendor_arm,
- cpuinfo_uarch_cortex_a55,
- 2420000000,
- },
- {cpuinfo_vendor_arm, cpuinfo_uarch_cortex_a76, 3150000000}}},
- /* Snapdragon (TM) 8cx Gen 3 @ 3.0 GHz */
- [woa_chip_name_microsoft_sq_3] =
- {L"Snapdragon (TM) 8cx Gen 3",
- woa_chip_name_microsoft_sq_3,
- {{
- cpuinfo_vendor_arm,
- cpuinfo_uarch_cortex_a78,
- 2420000000,
- },
- {cpuinfo_vendor_arm, cpuinfo_uarch_cortex_x1, 3000000000}}},
- /* Microsoft Windows Dev Kit 2023 */
- [woa_chip_name_microsoft_sq_3_devkit] =
- {L"Snapdragon Compute Platform",
- woa_chip_name_microsoft_sq_3_devkit,
- {{
- cpuinfo_vendor_arm,
- cpuinfo_uarch_cortex_a78,
- 2420000000,
- },
- {cpuinfo_vendor_arm, cpuinfo_uarch_cortex_x1, 3000000000}}},
- /* Ampere Altra */
- [woa_chip_name_ampere_altra] = {
- L"Ampere(R) Altra(R) Processor",
- woa_chip_name_ampere_altra,
- {{cpuinfo_vendor_arm, cpuinfo_uarch_neoverse_n1, 3000000000}}}};
+static struct woa_chip_info woa_chip_unknown = {L"Unknown", {{cpuinfo_vendor_unknown, cpuinfo_uarch_unknown, 0}}};
BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context) {
struct woa_chip_info* chip_info = NULL;
@@ -87,23 +35,6 @@
return true;
}
-bool get_core_uarch_for_efficiency(
- enum woa_chip_name chip,
- BYTE EfficiencyClass,
- enum cpuinfo_uarch* uarch,
- uint64_t* frequency) {
- /* For currently supported WoA chips, the Efficiency class selects
- * the pre-defined little and big core.
- * Any further supported SoC's logic should be implemented here.
- */
- if (uarch && frequency && chip < woa_chip_name_last && EfficiencyClass < MAX_WOA_VALID_EFFICIENCY_CLASSES) {
- *uarch = woa_chips[chip].uarchs[EfficiencyClass].uarch;
- *frequency = woa_chips[chip].uarchs[EfficiencyClass].frequency;
- return true;
- }
- return false;
-}
-
/* Static helper functions */
static wchar_t* read_registry(LPCWSTR subkey, LPCWSTR value) {
@@ -149,40 +80,117 @@
return text_buffer;
}
+static uint64_t read_registry_qword(LPCWSTR subkey, LPCWSTR value) {
+ DWORD key_type = 0;
+ DWORD data_size = sizeof(uint64_t);
+ const DWORD flags = RRF_RT_REG_QWORD; /* Only read QWORD (REG_QWORD) values */
+ uint64_t qword_value = 0;
+ LSTATUS result = RegGetValueW(HKEY_LOCAL_MACHINE, subkey, value, flags, &key_type, &qword_value, &data_size);
+ if (result != ERROR_SUCCESS || data_size != sizeof(uint64_t)) {
+ cpuinfo_log_error("Registry QWORD read error");
+ return 0;
+ }
+ return qword_value;
+}
+
+static uint64_t read_registry_dword(LPCWSTR subkey, LPCWSTR value) {
+ DWORD key_type = 0;
+ DWORD data_size = sizeof(DWORD);
+ DWORD dword_value = 0;
+ LSTATUS result = RegGetValueW(
+ HKEY_LOCAL_MACHINE,
+ subkey,
+ value,
+ RRF_RT_REG_DWORD,
+ &key_type,
+ &dword_value,
+ &data_size);
+ if (result != ERROR_SUCCESS || data_size != sizeof(DWORD)) {
+ cpuinfo_log_error("Registry DWORD read error");
+ return 0;
+ }
+ return (uint64_t)dword_value;
+}
+
+static wchar_t* wcsndup(const wchar_t* src, size_t n) {
+ size_t len = wcsnlen(src, n);
+ wchar_t* dup = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len + 1) * sizeof(wchar_t));
+ if (dup) {
+ wcsncpy_s(dup, len + 1, src, len);
+ dup[len] = L'\0';
+ }
+ return dup;
+}
+
+static struct core_info_by_chip_name get_core_info_from_midr(uint32_t midr, uint64_t frequency) {
+ struct core_info_by_chip_name info;
+ enum cpuinfo_vendor vendor;
+ enum cpuinfo_uarch uarch;
+
+#if CPUINFO_ARCH_ARM
+ bool has_vfpv4 = false;
+ cpuinfo_arm_decode_vendor_uarch(midr, has_vfpv4, &vendor, &uarch);
+#else
+ cpuinfo_arm_decode_vendor_uarch(midr, &vendor, &uarch);
+#endif
+
+ info.vendor = vendor;
+ info.uarch = uarch;
+ info.frequency = frequency;
+ return info;
+}
+
static struct woa_chip_info* get_system_info_from_registry(void) {
wchar_t* text_buffer = NULL;
LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
LPCWSTR chip_name_value = L"ProcessorNameString";
+ LPCWSTR chip_midr_value = L"CP 4000";
+ LPCWSTR chip_mhz_value = L"~MHz";
struct woa_chip_info* chip_info = NULL;
- HANDLE heap = GetProcessHeap();
-
/* Read processor model name from registry and find in the hard-coded
* list. */
text_buffer = read_registry(cpu0_subkey, chip_name_value);
if (text_buffer == NULL) {
- cpuinfo_log_error("Registry read error");
+ cpuinfo_log_error("Registry read error for processor name");
return NULL;
}
- for (uint32_t i = 0; i < (uint32_t)woa_chip_name_last; i++) {
- size_t compare_length = wcsnlen(woa_chips[i].chip_name_string, CPUINFO_PACKAGE_NAME_MAX);
- int compare_result = wcsncmp(text_buffer, woa_chips[i].chip_name_string, compare_length);
- if (compare_result == 0) {
- chip_info = woa_chips + i;
- break;
- }
- }
- if (chip_info == NULL) {
- /* No match was found, so print a warning and assign the unknown
- * case. */
- cpuinfo_log_error(
- "Unknown chip model name '%ls'.\nPlease add new Windows on Arm SoC/chip support to arm/windows/init.c!",
- text_buffer);
- } else {
- cpuinfo_log_debug("detected chip model name: %s", chip_info->chip_name_string);
- }
- HeapFree(heap, 0, text_buffer);
+ /*
+ * https://developer.arm.com/documentation/100442/0100/register-descriptions/aarch32-system-registers/midr--main-id-register
+ * Regedit for MIDR : HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\CP 4000
+ */
+ uint64_t midr_qword = (uint32_t)read_registry_qword(cpu0_subkey, chip_midr_value);
+ if (midr_qword == 0) {
+ cpuinfo_log_error("Registry read error for MIDR value");
+ return NULL;
+ }
+ // MIDR is only 32 bits, so we need to cast it to uint32_t
+ uint32_t midr_value = (uint32_t)midr_qword;
+
+ /* Read the frequency from the registry
+ * The value is in MHz, so we need to convert it to Hz */
+ uint64_t frequency_mhz = read_registry_dword(cpu0_subkey, chip_mhz_value);
+ if (frequency_mhz == 0) {
+ cpuinfo_log_error("Registry read error for frequency value");
+ return NULL;
+ }
+ // Convert MHz to Hz
+ uint64_t frequency_hz = frequency_mhz * 1000000;
+
+ // Allocate chip_info before using it.
+ chip_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct woa_chip_info));
+ if (chip_info == NULL) {
+ cpuinfo_log_error("Heap allocation error for chip_info");
+ return NULL;
+ }
+
+ // set chip_info fields
+ chip_info->chip_name_string = wcsndup(text_buffer, CPUINFO_PACKAGE_NAME_MAX - 1);
+ chip_info->uarchs[0] = get_core_info_from_midr(midr_value, frequency_hz);
+
+ cpuinfo_log_debug("detected chip model name: %ls", chip_info->chip_name_string);
+
return chip_info;
}
@@ -216,4 +224,4 @@
cpuinfo_isa.pmull = crypto;
cpuinfo_isa.crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
-}
+}
\ No newline at end of file
diff --git a/src/arm/windows/windows-arm-init.h b/src/arm/windows/windows-arm-init.h
index dc6e184..52dd180 100644
--- a/src/arm/windows/windows-arm-init.h
+++ b/src/arm/windows/windows-arm-init.h
@@ -3,17 +3,6 @@
/* Efficiency class = 0 means little core, while 1 means big core for now. */
#define MAX_WOA_VALID_EFFICIENCY_CLASSES 2
-/* List of known and supported Windows on Arm SoCs/chips. */
-enum woa_chip_name {
- woa_chip_name_microsoft_sq_1 = 0,
- woa_chip_name_microsoft_sq_2 = 1,
- woa_chip_name_microsoft_sq_3 = 2,
- woa_chip_name_microsoft_sq_3_devkit = 3,
- woa_chip_name_ampere_altra = 4,
- woa_chip_name_unknown = 5,
- woa_chip_name_last = woa_chip_name_unknown
-};
-
/* Topology information hard-coded by SoC/chip name */
struct core_info_by_chip_name {
enum cpuinfo_vendor vendor;
@@ -26,14 +15,7 @@
*/
struct woa_chip_info {
wchar_t* chip_name_string;
- enum woa_chip_name chip_name;
struct core_info_by_chip_name uarchs[MAX_WOA_VALID_EFFICIENCY_CLASSES];
};
-bool get_core_uarch_for_efficiency(
- enum woa_chip_name chip,
- BYTE EfficiencyClass,
- enum cpuinfo_uarch* uarch,
- uint64_t* frequency);
-
bool cpu_info_init_by_logical_sys_info(const struct woa_chip_info* chip_info, enum cpuinfo_vendor vendor);