Skip to content

Commit 1ba344e

Browse files
authored
- refactor for auto detection
1 parent b73ae6c commit 1ba344e

File tree

7 files changed

+135
-130
lines changed

7 files changed

+135
-130
lines changed

CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ IF(CPUINFO_SUPPORTED_PLATFORM)
187187
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "^Windows" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(ARM64|arm64)$")
188188
LIST(APPEND CPUINFO_SRCS
189189
src/arm/windows/init-by-logical-sys-info.c
190-
src/arm/windows/init.c)
190+
src/arm/windows/init.c
191+
src/arm/uarch.c)
191192
ELSEIF(CPUINFO_TARGET_PROCESSOR MATCHES "^(armv[5-8].*|aarch64|arm64.*)$" OR IOS_ARCH MATCHES "^(armv7.*|arm64.*)$")
192193
LIST(APPEND CPUINFO_SRCS
193194
src/arm/uarch.c

include/cpuinfo.h

+2
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,8 @@ enum cpuinfo_uarch {
522522
cpuinfo_uarch_falkor = 0x00400103,
523523
/** Qualcomm Saphira. */
524524
cpuinfo_uarch_saphira = 0x00400104,
525+
/** Qualcomm Oryon. */
526+
cpuinfo_uarch_oryon = 0x00400105,
525527

526528
/** Nvidia Denver. */
527529
cpuinfo_uarch_denver = 0x00500100,

src/arm/api.h

+17-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#pragma once
22

3+
#ifdef _MSC_VER
4+
#define RESTRICT_STATIC /* nothing for MSVC */
5+
#else
6+
#define RESTRICT_STATIC restrict static
7+
#endif
8+
39
#include <stdbool.h>
410
#include <stdint.h>
511

@@ -82,11 +88,11 @@ struct cpuinfo_arm_chipset {
8288

8389
#ifndef __cplusplus
8490
CPUINFO_INTERNAL void cpuinfo_arm_chipset_to_string(
85-
const struct cpuinfo_arm_chipset chipset[restrict static 1],
86-
char name[restrict static CPUINFO_ARM_CHIPSET_NAME_MAX]);
91+
const struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
92+
char name[RESTRICT_STATIC CPUINFO_ARM_CHIPSET_NAME_MAX]);
8793

8894
CPUINFO_INTERNAL void cpuinfo_arm_fixup_chipset(
89-
struct cpuinfo_arm_chipset chipset[restrict static 1],
95+
struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
9096
uint32_t cores,
9197
uint32_t max_cpu_freq_max);
9298

@@ -95,23 +101,23 @@ CPUINFO_INTERNAL void cpuinfo_arm_decode_vendor_uarch(
95101
#if CPUINFO_ARCH_ARM
96102
bool has_vfpv4,
97103
#endif
98-
enum cpuinfo_vendor vendor[restrict static 1],
99-
enum cpuinfo_uarch uarch[restrict static 1]);
104+
enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
105+
enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]);
100106

101107
CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
102108
enum cpuinfo_uarch uarch,
103109
uint32_t cluster_cores,
104110
uint32_t midr,
105-
const struct cpuinfo_arm_chipset chipset[restrict static 1],
111+
const struct cpuinfo_arm_chipset chipset[RESTRICT_STATIC 1],
106112
uint32_t cluster_id,
107113
uint32_t arch_version,
108-
struct cpuinfo_cache l1i[restrict static 1],
109-
struct cpuinfo_cache l1d[restrict static 1],
110-
struct cpuinfo_cache l2[restrict static 1],
111-
struct cpuinfo_cache l3[restrict static 1]);
114+
struct cpuinfo_cache l1i[RESTRICT_STATIC 1],
115+
struct cpuinfo_cache l1d[RESTRICT_STATIC 1],
116+
struct cpuinfo_cache l2[RESTRICT_STATIC 1],
117+
struct cpuinfo_cache l3[RESTRICT_STATIC 1]);
112118

113119
CPUINFO_INTERNAL uint32_t
114-
cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor processor[restrict static 1]);
120+
cpuinfo_arm_compute_max_cache_size(const struct cpuinfo_processor processor[RESTRICT_STATIC 1]);
115121
#else /* defined(__cplusplus) */
116122
CPUINFO_INTERNAL void cpuinfo_arm_decode_cache(
117123
enum cpuinfo_uarch uarch,

src/arm/uarch.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ void cpuinfo_arm_decode_vendor_uarch(
99
#if CPUINFO_ARCH_ARM
1010
bool has_vfpv4,
1111
#endif /* CPUINFO_ARCH_ARM */
12-
enum cpuinfo_vendor vendor[restrict static 1],
13-
enum cpuinfo_uarch uarch[restrict static 1]) {
12+
enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
13+
enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]) {
1414
switch (midr_get_implementer(midr)) {
1515
case 'A':
1616
*vendor = cpuinfo_vendor_arm;
@@ -332,6 +332,9 @@ void cpuinfo_arm_decode_vendor_uarch(
332332
*uarch = cpuinfo_uarch_cortex_a55;
333333
break;
334334
#if CPUINFO_ARCH_ARM64
335+
case 0x001:
336+
*uarch = cpuinfo_uarch_oryon;
337+
break;
335338
case 0xC00:
336339
*uarch = cpuinfo_uarch_falkor;
337340
break;

src/arm/windows/init-by-logical-sys-info.c

+8-5
Original file line numberDiff line numberDiff line change
@@ -750,11 +750,14 @@ void store_core_info_per_processor(
750750
if (cores) {
751751
processors[processor_global_index].core = cores + core_id;
752752
cores[core_id].core_id = core_id;
753-
get_core_uarch_for_efficiency(
754-
chip_info->chip_name,
755-
core_info->Processor.EfficiencyClass,
756-
&(cores[core_id].uarch),
757-
&(cores[core_id].frequency));
753+
754+
if (chip_info->uarchs == NULL) {
755+
cpuinfo_log_error("uarch is NULL for core %d", core_id);
756+
return;
757+
}
758+
759+
cores[core_id].uarch = chip_info->uarchs[0].uarch;
760+
cores[core_id].frequency = chip_info->uarchs[0].frequency;
758761

759762
/* We don't have cluster information, so we handle it as
760763
* fixed 1 to (cluster / cores).

src/arm/windows/init.c

+101-93
Original file line numberDiff line numberDiff line change
@@ -7,69 +7,17 @@
77
#include <cpuinfo/internal-api.h>
88
#include <cpuinfo/log.h>
99

10+
#include <arm/api.h>
11+
#include <arm/midr.h>
12+
1013
#include "windows-arm-init.h"
1114

1215
struct cpuinfo_arm_isa cpuinfo_isa;
1316

1417
static void set_cpuinfo_isa_fields(void);
1518
static struct woa_chip_info* get_system_info_from_registry(void);
1619

17-
static struct woa_chip_info woa_chip_unknown = {
18-
L"Unknown",
19-
woa_chip_name_unknown,
20-
{{cpuinfo_vendor_unknown, cpuinfo_uarch_unknown, 0}}};
21-
22-
/* Please add new SoC/chip info here! */
23-
static struct woa_chip_info woa_chips[woa_chip_name_last] = {
24-
/* Microsoft SQ1 Kryo 495 4 + 4 cores (3 GHz + 1.80 GHz) */
25-
[woa_chip_name_microsoft_sq_1] =
26-
{L"Microsoft SQ1",
27-
woa_chip_name_microsoft_sq_1,
28-
{{
29-
cpuinfo_vendor_arm,
30-
cpuinfo_uarch_cortex_a55,
31-
1800000000,
32-
},
33-
{
34-
cpuinfo_vendor_arm,
35-
cpuinfo_uarch_cortex_a76,
36-
3000000000,
37-
}}},
38-
/* Microsoft SQ2 Kryo 495 4 + 4 cores (3.15 GHz + 2.42 GHz) */
39-
[woa_chip_name_microsoft_sq_2] =
40-
{L"Microsoft SQ2",
41-
woa_chip_name_microsoft_sq_2,
42-
{{
43-
cpuinfo_vendor_arm,
44-
cpuinfo_uarch_cortex_a55,
45-
2420000000,
46-
},
47-
{cpuinfo_vendor_arm, cpuinfo_uarch_cortex_a76, 3150000000}}},
48-
/* Snapdragon (TM) 8cx Gen 3 @ 3.0 GHz */
49-
[woa_chip_name_microsoft_sq_3] =
50-
{L"Snapdragon (TM) 8cx Gen 3",
51-
woa_chip_name_microsoft_sq_3,
52-
{{
53-
cpuinfo_vendor_arm,
54-
cpuinfo_uarch_cortex_a78,
55-
2420000000,
56-
},
57-
{cpuinfo_vendor_arm, cpuinfo_uarch_cortex_x1, 3000000000}}},
58-
/* Microsoft Windows Dev Kit 2023 */
59-
[woa_chip_name_microsoft_sq_3_devkit] =
60-
{L"Snapdragon Compute Platform",
61-
woa_chip_name_microsoft_sq_3_devkit,
62-
{{
63-
cpuinfo_vendor_arm,
64-
cpuinfo_uarch_cortex_a78,
65-
2420000000,
66-
},
67-
{cpuinfo_vendor_arm, cpuinfo_uarch_cortex_x1, 3000000000}}},
68-
/* Ampere Altra */
69-
[woa_chip_name_ampere_altra] = {
70-
L"Ampere(R) Altra(R) Processor",
71-
woa_chip_name_ampere_altra,
72-
{{cpuinfo_vendor_arm, cpuinfo_uarch_neoverse_n1, 3000000000}}}};
20+
static struct woa_chip_info woa_chip_unknown = {L"Unknown", {{cpuinfo_vendor_unknown, cpuinfo_uarch_unknown, 0}}};
7321

7422
BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PVOID* context) {
7523
struct woa_chip_info* chip_info = NULL;
@@ -87,23 +35,6 @@ BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
8735
return true;
8836
}
8937

90-
bool get_core_uarch_for_efficiency(
91-
enum woa_chip_name chip,
92-
BYTE EfficiencyClass,
93-
enum cpuinfo_uarch* uarch,
94-
uint64_t* frequency) {
95-
/* For currently supported WoA chips, the Efficiency class selects
96-
* the pre-defined little and big core.
97-
* Any further supported SoC's logic should be implemented here.
98-
*/
99-
if (uarch && frequency && chip < woa_chip_name_last && EfficiencyClass < MAX_WOA_VALID_EFFICIENCY_CLASSES) {
100-
*uarch = woa_chips[chip].uarchs[EfficiencyClass].uarch;
101-
*frequency = woa_chips[chip].uarchs[EfficiencyClass].frequency;
102-
return true;
103-
}
104-
return false;
105-
}
106-
10738
/* Static helper functions */
10839

10940
static wchar_t* read_registry(LPCWSTR subkey, LPCWSTR value) {
@@ -149,40 +80,117 @@ static wchar_t* read_registry(LPCWSTR subkey, LPCWSTR value) {
14980
return text_buffer;
15081
}
15182

83+
static uint64_t read_registry_qword(LPCWSTR subkey, LPCWSTR value) {
84+
DWORD key_type = 0;
85+
DWORD data_size = sizeof(uint64_t);
86+
const DWORD flags = RRF_RT_REG_QWORD; /* Only read QWORD (REG_QWORD) values */
87+
uint64_t qword_value = 0;
88+
LSTATUS result = RegGetValueW(HKEY_LOCAL_MACHINE, subkey, value, flags, &key_type, &qword_value, &data_size);
89+
if (result != ERROR_SUCCESS || data_size != sizeof(uint64_t)) {
90+
cpuinfo_log_error("Registry QWORD read error");
91+
return 0;
92+
}
93+
return qword_value;
94+
}
95+
96+
static uint64_t read_registry_dword(LPCWSTR subkey, LPCWSTR value) {
97+
DWORD key_type = 0;
98+
DWORD data_size = sizeof(DWORD);
99+
DWORD dword_value = 0;
100+
LSTATUS result = RegGetValueW(
101+
HKEY_LOCAL_MACHINE,
102+
subkey,
103+
value,
104+
RRF_RT_REG_DWORD,
105+
&key_type,
106+
&dword_value,
107+
&data_size);
108+
if (result != ERROR_SUCCESS || data_size != sizeof(DWORD)) {
109+
cpuinfo_log_error("Registry DWORD read error");
110+
return 0;
111+
}
112+
return (uint64_t)dword_value;
113+
}
114+
115+
static wchar_t* wcsndup(const wchar_t* src, size_t n) {
116+
size_t len = wcsnlen(src, n);
117+
wchar_t* dup = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (len + 1) * sizeof(wchar_t));
118+
if (dup) {
119+
wcsncpy_s(dup, len + 1, src, len);
120+
dup[len] = L'\0';
121+
}
122+
return dup;
123+
}
124+
125+
static struct core_info_by_chip_name get_core_info_from_midr(uint32_t midr, uint64_t frequency) {
126+
struct core_info_by_chip_name info;
127+
enum cpuinfo_vendor vendor;
128+
enum cpuinfo_uarch uarch;
129+
130+
#if CPUINFO_ARCH_ARM
131+
bool has_vfpv4 = false;
132+
cpuinfo_arm_decode_vendor_uarch(midr, has_vfpv4, &vendor, &uarch);
133+
#else
134+
cpuinfo_arm_decode_vendor_uarch(midr, &vendor, &uarch);
135+
#endif
136+
137+
info.vendor = vendor;
138+
info.uarch = uarch;
139+
info.frequency = frequency;
140+
return info;
141+
}
142+
152143
static struct woa_chip_info* get_system_info_from_registry(void) {
153144
wchar_t* text_buffer = NULL;
154145
LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
155146
LPCWSTR chip_name_value = L"ProcessorNameString";
147+
LPCWSTR chip_midr_value = L"CP 4000";
148+
LPCWSTR chip_mhz_value = L"~MHz";
156149
struct woa_chip_info* chip_info = NULL;
157150

158-
HANDLE heap = GetProcessHeap();
159-
160151
/* Read processor model name from registry and find in the hard-coded
161152
* list. */
162153
text_buffer = read_registry(cpu0_subkey, chip_name_value);
163154
if (text_buffer == NULL) {
164-
cpuinfo_log_error("Registry read error");
155+
cpuinfo_log_error("Registry read error for processor name");
165156
return NULL;
166157
}
167-
for (uint32_t i = 0; i < (uint32_t)woa_chip_name_last; i++) {
168-
size_t compare_length = wcsnlen(woa_chips[i].chip_name_string, CPUINFO_PACKAGE_NAME_MAX);
169-
int compare_result = wcsncmp(text_buffer, woa_chips[i].chip_name_string, compare_length);
170-
if (compare_result == 0) {
171-
chip_info = woa_chips + i;
172-
break;
173-
}
158+
159+
/*
160+
* https://developer.arm.com/documentation/100442/0100/register-descriptions/aarch32-system-registers/midr--main-id-register
161+
* Regedit for MIDR : HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\CP 4000
162+
*/
163+
uint64_t midr_qword = (uint32_t)read_registry_qword(cpu0_subkey, chip_midr_value);
164+
if (midr_qword == 0) {
165+
cpuinfo_log_error("Registry read error for MIDR value");
166+
return NULL;
174167
}
175-
if (chip_info == NULL) {
176-
/* No match was found, so print a warning and assign the unknown
177-
* case. */
178-
cpuinfo_log_error(
179-
"Unknown chip model name '%ls'.\nPlease add new Windows on Arm SoC/chip support to arm/windows/init.c!",
180-
text_buffer);
181-
} else {
182-
cpuinfo_log_debug("detected chip model name: %s", chip_info->chip_name_string);
168+
// MIDR is only 32 bits, so we need to cast it to uint32_t
169+
uint32_t midr_value = (uint32_t)midr_qword;
170+
171+
/* Read the frequency from the registry
172+
* The value is in MHz, so we need to convert it to Hz */
173+
uint64_t frequency_mhz = read_registry_dword(cpu0_subkey, chip_mhz_value);
174+
if (frequency_mhz == 0) {
175+
cpuinfo_log_error("Registry read error for frequency value");
176+
return NULL;
183177
}
178+
// Convert MHz to Hz
179+
uint64_t frequency_hz = frequency_mhz * 1000000;
180+
181+
// Allocate chip_info before using it.
182+
chip_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct woa_chip_info));
183+
if (chip_info == NULL) {
184+
cpuinfo_log_error("Heap allocation error for chip_info");
185+
return NULL;
186+
}
187+
188+
// set chip_info fields
189+
chip_info->chip_name_string = wcsndup(text_buffer, CPUINFO_PACKAGE_NAME_MAX - 1);
190+
chip_info->uarchs[0] = get_core_info_from_midr(midr_value, frequency_hz);
191+
192+
cpuinfo_log_debug("detected chip model name: %ls", chip_info->chip_name_string);
184193

185-
HeapFree(heap, 0, text_buffer);
186194
return chip_info;
187195
}
188196

@@ -216,4 +224,4 @@ static void set_cpuinfo_isa_fields(void) {
216224
cpuinfo_isa.pmull = crypto;
217225

218226
cpuinfo_isa.crc32 = IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0;
219-
}
227+
}

src/arm/windows/windows-arm-init.h

-18
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,6 @@
33
/* Efficiency class = 0 means little core, while 1 means big core for now. */
44
#define MAX_WOA_VALID_EFFICIENCY_CLASSES 2
55

6-
/* List of known and supported Windows on Arm SoCs/chips. */
7-
enum woa_chip_name {
8-
woa_chip_name_microsoft_sq_1 = 0,
9-
woa_chip_name_microsoft_sq_2 = 1,
10-
woa_chip_name_microsoft_sq_3 = 2,
11-
woa_chip_name_microsoft_sq_3_devkit = 3,
12-
woa_chip_name_ampere_altra = 4,
13-
woa_chip_name_unknown = 5,
14-
woa_chip_name_last = woa_chip_name_unknown
15-
};
16-
176
/* Topology information hard-coded by SoC/chip name */
187
struct core_info_by_chip_name {
198
enum cpuinfo_vendor vendor;
@@ -26,14 +15,7 @@ struct core_info_by_chip_name {
2615
*/
2716
struct woa_chip_info {
2817
wchar_t* chip_name_string;
29-
enum woa_chip_name chip_name;
3018
struct core_info_by_chip_name uarchs[MAX_WOA_VALID_EFFICIENCY_CLASSES];
3119
};
3220

33-
bool get_core_uarch_for_efficiency(
34-
enum woa_chip_name chip,
35-
BYTE EfficiencyClass,
36-
enum cpuinfo_uarch* uarch,
37-
uint64_t* frequency);
38-
3921
bool cpu_info_init_by_logical_sys_info(const struct woa_chip_info* chip_info, enum cpuinfo_vendor vendor);

0 commit comments

Comments
 (0)