7
7
#include <cpuinfo/internal-api.h>
8
8
#include <cpuinfo/log.h>
9
9
10
+ #include <arm/api.h>
11
+ #include <arm/midr.h>
12
+
10
13
#include "windows-arm-init.h"
11
14
12
15
struct cpuinfo_arm_isa cpuinfo_isa ;
13
16
14
17
static void set_cpuinfo_isa_fields (void );
15
18
static struct woa_chip_info * get_system_info_from_registry (void );
16
19
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 }}};
73
21
74
22
BOOL CALLBACK cpuinfo_arm_windows_init (PINIT_ONCE init_once , PVOID parameter , PVOID * context ) {
75
23
struct woa_chip_info * chip_info = NULL ;
@@ -87,23 +35,6 @@ BOOL CALLBACK cpuinfo_arm_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
87
35
return true;
88
36
}
89
37
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
-
107
38
/* Static helper functions */
108
39
109
40
static wchar_t * read_registry (LPCWSTR subkey , LPCWSTR value ) {
@@ -149,40 +80,112 @@ static wchar_t* read_registry(LPCWSTR subkey, LPCWSTR value) {
149
80
return text_buffer ;
150
81
}
151
82
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 =
101
+ RegGetValueW (HKEY_LOCAL_MACHINE , subkey , value , RRF_RT_REG_DWORD , & key_type , & dword_value , & data_size );
102
+ if (result != ERROR_SUCCESS || data_size != sizeof (DWORD )) {
103
+ cpuinfo_log_error ("Registry DWORD read error" );
104
+ return 0 ;
105
+ }
106
+ return (uint64_t )dword_value ;
107
+ }
108
+
109
+ static wchar_t * wcsndup (const wchar_t * src , size_t n ) {
110
+ size_t len = wcsnlen (src , n );
111
+ wchar_t * dup = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY , (len + 1 ) * sizeof (wchar_t ));
112
+ if (dup ) {
113
+ wcsncpy_s (dup , len + 1 , src , len );
114
+ dup [len ] = L'\0' ;
115
+ }
116
+ return dup ;
117
+ }
118
+
119
+ static struct core_info_by_chip_name get_core_info_from_midr (uint32_t midr , uint64_t frequency ) {
120
+ struct core_info_by_chip_name info ;
121
+ enum cpuinfo_vendor vendor ;
122
+ enum cpuinfo_uarch uarch ;
123
+
124
+ #if CPUINFO_ARCH_ARM
125
+ bool has_vfpv4 = false;
126
+ cpuinfo_arm_decode_vendor_uarch (midr , has_vfpv4 , & vendor , & uarch );
127
+ #else
128
+ cpuinfo_arm_decode_vendor_uarch (midr , & vendor , & uarch );
129
+ #endif
130
+
131
+ info .vendor = vendor ;
132
+ info .uarch = uarch ;
133
+ info .frequency = frequency ;
134
+ return info ;
135
+ }
136
+
152
137
static struct woa_chip_info * get_system_info_from_registry (void ) {
153
138
wchar_t * text_buffer = NULL ;
154
139
LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" ;
155
140
LPCWSTR chip_name_value = L"ProcessorNameString" ;
141
+ LPCWSTR chip_midr_value = L"CP 4000" ;
142
+ LPCWSTR chip_mhz_value = L"~MHz" ;
156
143
struct woa_chip_info * chip_info = NULL ;
157
144
158
- HANDLE heap = GetProcessHeap ();
159
-
160
145
/* Read processor model name from registry and find in the hard-coded
161
146
* list. */
162
147
text_buffer = read_registry (cpu0_subkey , chip_name_value );
163
148
if (text_buffer == NULL ) {
164
- cpuinfo_log_error ("Registry read error" );
149
+ cpuinfo_log_error ("Registry read error for processor name " );
165
150
return NULL ;
166
151
}
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
- }
152
+
153
+ /*
154
+ * https://developer.arm.com/documentation/100442/0100/register-descriptions/aarch32-system-registers/midr--main-id-register
155
+ * Regedit for MIDR :
156
+ *HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0\CP 4000
157
+ */
158
+ uint64_t midr_qword = (uint32_t )read_registry_qword (cpu0_subkey , chip_midr_value );
159
+ if (midr_qword == 0 ) {
160
+ cpuinfo_log_error ("Registry read error for MIDR value" );
161
+ return NULL ;
162
+ }
163
+ // MIDR is only 32 bits, so we need to cast it to uint32_t
164
+ uint32_t midr_value = (uint32_t )midr_qword ;
165
+
166
+ /* Read the frequency from the registry
167
+ * The value is in MHz, so we need to convert it to Hz */
168
+ uint64_t frequency_mhz = read_registry_dword (cpu0_subkey , chip_mhz_value );
169
+ if (frequency_mhz == 0 ) {
170
+ cpuinfo_log_error ("Registry read error for frequency value" );
171
+ return NULL ;
174
172
}
173
+ // Convert MHz to Hz
174
+ uint64_t frequency_hz = frequency_mhz * 1000000 ;
175
+
176
+ // Allocate chip_info before using it.
177
+ chip_info = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY , sizeof (struct woa_chip_info ));
175
178
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 );
179
+ cpuinfo_log_error ("Heap allocation error for chip_info" );
180
+ return NULL ;
183
181
}
184
182
185
- HeapFree (heap , 0 , text_buffer );
183
+ // set chip_info fields
184
+ chip_info -> chip_name_string = wcsndup (text_buffer , CPUINFO_PACKAGE_NAME_MAX - 1 );
185
+ chip_info -> uarchs [0 ] = get_core_info_from_midr (midr_value , frequency_hz );
186
+
187
+ cpuinfo_log_debug ("detected chip model name: %ls" , chip_info -> chip_name_string );
188
+
186
189
return chip_info ;
187
190
}
188
191
@@ -216,4 +219,4 @@ static void set_cpuinfo_isa_fields(void) {
216
219
cpuinfo_isa .pmull = crypto ;
217
220
218
221
cpuinfo_isa .crc32 = IsProcessorFeaturePresent (PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE ) != 0 ;
219
- }
222
+ }
0 commit comments