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
1215struct cpuinfo_arm_isa cpuinfo_isa ;
1316
1417static void set_cpuinfo_isa_fields (void );
1518static 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
7422BOOL 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
10940static wchar_t * read_registry (LPCWSTR subkey , LPCWSTR value ) {
@@ -149,40 +80,112 @@ 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 =
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+
152137static struct woa_chip_info * get_system_info_from_registry (void ) {
153138 wchar_t * text_buffer = NULL ;
154139 LPCWSTR cpu0_subkey = L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0" ;
155140 LPCWSTR chip_name_value = L"ProcessorNameString" ;
141+ LPCWSTR chip_midr_value = L"CP 4000" ;
142+ LPCWSTR chip_mhz_value = L"~MHz" ;
156143 struct woa_chip_info * chip_info = NULL ;
157144
158- HANDLE heap = GetProcessHeap ();
159-
160145 /* Read processor model name from registry and find in the hard-coded
161146 * list. */
162147 text_buffer = read_registry (cpu0_subkey , chip_name_value );
163148 if (text_buffer == NULL ) {
164- cpuinfo_log_error ("Registry read error" );
149+ cpuinfo_log_error ("Registry read error for processor name " );
165150 return NULL ;
166151 }
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 ;
174172 }
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 ));
175178 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 ;
183181 }
184182
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+
186189 return chip_info ;
187190}
188191
@@ -216,4 +219,4 @@ static void set_cpuinfo_isa_fields(void) {
216219 cpuinfo_isa .pmull = crypto ;
217220
218221 cpuinfo_isa .crc32 = IsProcessorFeaturePresent (PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE ) != 0 ;
219- }
222+ }
0 commit comments