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,117 @@ 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 = 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
+
152
143
static struct woa_chip_info * get_system_info_from_registry (void ) {
153
144
wchar_t * text_buffer = NULL ;
154
145
LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" ;
155
146
LPCWSTR chip_name_value = L"ProcessorNameString" ;
147
+ LPCWSTR chip_midr_value = L"CP 4000" ;
148
+ LPCWSTR chip_mhz_value = L"~MHz" ;
156
149
struct woa_chip_info * chip_info = NULL ;
157
150
158
- HANDLE heap = GetProcessHeap ();
159
-
160
151
/* Read processor model name from registry and find in the hard-coded
161
152
* list. */
162
153
text_buffer = read_registry (cpu0_subkey , chip_name_value );
163
154
if (text_buffer == NULL ) {
164
- cpuinfo_log_error ("Registry read error" );
155
+ cpuinfo_log_error ("Registry read error for processor name " );
165
156
return NULL ;
166
157
}
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 ;
174
167
}
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 ;
183
177
}
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 );
184
193
185
- HeapFree (heap , 0 , text_buffer );
186
194
return chip_info ;
187
195
}
188
196
@@ -216,4 +224,4 @@ static void set_cpuinfo_isa_fields(void) {
216
224
cpuinfo_isa .pmull = crypto ;
217
225
218
226
cpuinfo_isa .crc32 = IsProcessorFeaturePresent (PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE ) != 0 ;
219
- }
227
+ }
0 commit comments