1 // Windows/SystemInfo.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../C/CpuArch.h"
6
7 #include "../Common/IntToString.h"
8 #include "../Common/StringConvert.h"
9
10 #ifdef _WIN32
11
12 #include "Registry.h"
13
14 #else
15
16 #include <unistd.h>
17 #include <sys/utsname.h>
18 #ifdef __APPLE__
19 #include <sys/sysctl.h>
20
21 #elif !defined(_AIX)
22
23 #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
24 #define Z7_GETAUXV_AVAILABLE
25 #else
26 // #pragma message("=== is not NEW GLIBC === ")
27 #if defined __has_include
28 #if __has_include (<sys/auxv.h>)
29 // #pragma message("=== sys/auxv.h is avail=== ")
30 #define Z7_GETAUXV_AVAILABLE
31 #endif
32 #endif
33 #endif
34
35 #ifdef Z7_GETAUXV_AVAILABLE
36 // #if defined __has_include
37 // #if __has_include (<sys/auxv.h>)
38 #include <sys/auxv.h>
39 #define USE_HWCAP
40 // #endif
41 // #endif
42
43 // #undef AT_HWCAP // to debug
44 // #undef AT_HWCAP2 // to debug
45
46 /* the following patch for some debian systems.
47 Is it OK to define AT_HWCAP and AT_HWCAP2 here with these constant numbers? */
48 /*
49 #if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
50 #ifndef AT_HWCAP
51 #define AT_HWCAP 16
52 #endif
53 #ifndef AT_HWCAP2
54 #define AT_HWCAP2 26
55 #endif
56 #endif
57 */
58
59 #ifdef USE_HWCAP
60
61 #if defined(__FreeBSD__)
62
63 // #if (__FreeBSD__ >= 13) // (FreeBSD 12.01 is required for elf_aux_info() ???)
MY_getauxval(int aux)64 static unsigned long MY_getauxval(int aux)
65 {
66 unsigned long val;
67 if (elf_aux_info(aux, &val, sizeof(val)))
68 return 0;
69 return val;
70 }
71
72 #else // ! __FreeBSD__
73
74 #ifdef MY_CPU_ARM_OR_ARM64
75 #if defined __has_include
76 #if __has_include (<asm/hwcap.h>)
77 #include <asm/hwcap.h>
78 #endif
79 #endif
80 #endif
81
82 #if defined(AT_HWCAP) || defined(AT_HWCAP2)
83 #define MY_getauxval getauxval
84 #endif
85
86 #endif // ! __FreeBSD__
87 #endif // USE_HWCAP
88 #endif // Z7_GETAUXV_AVAILABLE
89
90 #endif // !defined(_AIX)
91
92 #ifdef __linux__
93 #include "../Windows/FileIO.h"
94 #endif
95
96 #endif // WIN32
97
98 #include "SystemInfo.h"
99 #include "System.h"
100
101 using namespace NWindows;
102
103 #ifdef __linux__
104
ReadFile_to_Buffer(CFSTR fileName,CByteBuffer & buf)105 static bool ReadFile_to_Buffer(CFSTR fileName, CByteBuffer &buf)
106 {
107 NWindows::NFile::NIO::CInFile file;
108 if (!file.Open(fileName))
109 return false;
110 /*
111 UInt64 size;
112 if (!file.GetLength(size))
113 {
114 // GetLength() doesn't work "/proc/cpuinfo"
115 return false;
116 }
117 if (size >= ((UInt32)1 << 29))
118 return false;
119 */
120 size_t size = 0;
121 size_t addSize = (size_t)1 << 12;
122 for (;;)
123 {
124 // printf("\nsize = %d\n", (unsigned)size);
125 buf.ChangeSize_KeepData(size + addSize, size);
126 size_t processed;
127 if (!file.ReadFull(buf.NonConstData() + size, addSize, processed))
128 return false;
129 if (processed == 0)
130 {
131 buf.ChangeSize_KeepData(size, size);
132 return true;
133 }
134 size += processed;
135 addSize *= 2;
136 }
137 }
138
139 #endif
140
141
142 #if defined(_WIN32) || defined(AT_HWCAP) || defined(AT_HWCAP2)
PrintHex(AString & s,UInt64 v)143 static void PrintHex(AString &s, UInt64 v)
144 {
145 char temp[32];
146 ConvertUInt64ToHex(v, temp);
147 s += temp;
148 }
149 #endif
150
151 #ifdef MY_CPU_X86_OR_AMD64
152
153 Z7_NO_INLINE
PrintCpuChars(AString & s,UInt32 v)154 static void PrintCpuChars(AString &s, UInt32 v)
155 {
156 for (unsigned j = 0; j < 4; j++)
157 {
158 const Byte b = (Byte)(v & 0xFF);
159 v >>= 8;
160 if (b == 0)
161 break;
162 if (b >= 0x20 && b <= 0x7f)
163 s.Add_Char((char)b);
164 else
165 {
166 s.Add_Char('[');
167 char temp[16];
168 ConvertUInt32ToHex(b, temp);
169 s += temp;
170 s.Add_Char(']');
171 }
172 }
173 }
174
175
x86cpuid_to_String(AString & s)176 static void x86cpuid_to_String(AString &s)
177 {
178 s.Empty();
179
180 UInt32 a[4];
181 // cpuid was called already. So we don't check for cpuid availability here
182 z7_x86_cpuid(a, 0x80000000);
183
184 if (a[0] >= 0x80000004) // if (maxFunc2 >= hi+4) the full name is available
185 {
186 for (unsigned i = 0; i < 3; i++)
187 {
188 z7_x86_cpuid(a, (UInt32)(0x80000002 + i));
189 for (unsigned j = 0; j < 4; j++)
190 PrintCpuChars(s, a[j]);
191 }
192 }
193
194 s.Trim();
195
196 if (s.IsEmpty())
197 {
198 z7_x86_cpuid(a, 0);
199 for (unsigned i = 1; i < 4; i++)
200 {
201 const unsigned j = (i ^ (i >> 1));
202 PrintCpuChars(s, a[j]);
203 }
204 s.Trim();
205 }
206 }
207
208 /*
209 static void x86cpuid_all_to_String(AString &s)
210 {
211 Cx86cpuid p;
212 if (!x86cpuid_CheckAndRead(&p))
213 return;
214 s += "x86cpuid maxFunc = ";
215 s.Add_UInt32(p.maxFunc);
216 for (unsigned j = 0; j <= p.maxFunc; j++)
217 {
218 s.Add_LF();
219 // s.Add_UInt32(j); // align
220 {
221 char temp[32];
222 ConvertUInt32ToString(j, temp);
223 unsigned len = (unsigned)strlen(temp);
224 while (len < 8)
225 {
226 len++;
227 s.Add_Space();
228 }
229 s += temp;
230 }
231
232 s += ":";
233 UInt32 d[4] = { 0 };
234 MyCPUID(j, &d[0], &d[1], &d[2], &d[3]);
235 for (unsigned i = 0; i < 4; i++)
236 {
237 char temp[32];
238 ConvertUInt32ToHex8Digits(d[i], temp);
239 s.Add_Space();
240 s += temp;
241 }
242 }
243 }
244 */
245
246 #endif
247
248
249
250 #ifdef _WIN32
251
252 static const char * const k_PROCESSOR_ARCHITECTURE[] =
253 {
254 "x86" // "INTEL"
255 , "MIPS"
256 , "ALPHA"
257 , "PPC"
258 , "SHX"
259 , "ARM"
260 , "IA64"
261 , "ALPHA64"
262 , "MSIL"
263 , "x64" // "AMD64"
264 , "IA32_ON_WIN64"
265 , "NEUTRAL"
266 , "ARM64"
267 , "ARM32_ON_WIN64"
268 };
269
270 #define Z7_WIN_PROCESSOR_ARCHITECTURE_INTEL 0
271 #define Z7_WIN_PROCESSOR_ARCHITECTURE_AMD64 9
272
273
274 #define Z7_WIN_PROCESSOR_INTEL_PENTIUM 586
275 #define Z7_WIN_PROCESSOR_AMD_X8664 8664
276
277 /*
278 static const CUInt32PCharPair k_PROCESSOR[] =
279 {
280 { 2200, "IA64" },
281 { 8664, "x64" }
282 };
283
284 #define PROCESSOR_INTEL_386 386
285 #define PROCESSOR_INTEL_486 486
286 #define PROCESSOR_INTEL_PENTIUM 586
287 #define PROCESSOR_INTEL_860 860
288 #define PROCESSOR_INTEL_IA64 2200
289 #define PROCESSOR_AMD_X8664 8664
290 #define PROCESSOR_MIPS_R2000 2000
291 #define PROCESSOR_MIPS_R3000 3000
292 #define PROCESSOR_MIPS_R4000 4000
293 #define PROCESSOR_ALPHA_21064 21064
294 #define PROCESSOR_PPC_601 601
295 #define PROCESSOR_PPC_603 603
296 #define PROCESSOR_PPC_604 604
297 #define PROCESSOR_PPC_620 620
298 #define PROCESSOR_HITACHI_SH3 10003
299 #define PROCESSOR_HITACHI_SH3E 10004
300 #define PROCESSOR_HITACHI_SH4 10005
301 #define PROCESSOR_MOTOROLA_821 821
302 #define PROCESSOR_SHx_SH3 103
303 #define PROCESSOR_SHx_SH4 104
304 #define PROCESSOR_STRONGARM 2577 // 0xA11
305 #define PROCESSOR_ARM720 1824 // 0x720
306 #define PROCESSOR_ARM820 2080 // 0x820
307 #define PROCESSOR_ARM920 2336 // 0x920
308 #define PROCESSOR_ARM_7TDMI 70001
309 #define PROCESSOR_OPTIL 18767 // 0x494f
310 */
311
312
313 /*
314 static const char * const k_PF[] =
315 {
316 "FP_ERRATA"
317 , "FP_EMU"
318 , "CMPXCHG"
319 , "MMX"
320 , "PPC_MOVEMEM_64BIT"
321 , "ALPHA_BYTE"
322 , "SSE"
323 , "3DNOW"
324 , "RDTSC"
325 , "PAE"
326 , "SSE2"
327 , "SSE_DAZ"
328 , "NX"
329 , "SSE3"
330 , "CMPXCHG16B"
331 , "CMP8XCHG16"
332 , "CHANNELS"
333 , "XSAVE"
334 , "ARM_VFP_32"
335 , "ARM_NEON"
336 , "L2AT"
337 , "VIRT_FIRMWARE"
338 , "RDWRFSGSBASE"
339 , "FASTFAIL"
340 , "ARM_DIVIDE"
341 , "ARM_64BIT_LOADSTORE_ATOMIC"
342 , "ARM_EXTERNAL_CACHE"
343 , "ARM_FMAC"
344 , "RDRAND"
345 , "ARM_V8"
346 , "ARM_V8_CRYPTO"
347 , "ARM_V8_CRC32"
348 , "RDTSCP"
349 , "RDPID"
350 , "ARM_V81_ATOMIC"
351 , "MONITORX"
352 };
353 */
354
355 #endif
356
357
PrintPage(AString & s,UInt64 v)358 static void PrintPage(AString &s, UInt64 v)
359 {
360 const char *t = "B";
361 if ((v & 0x3ff) == 0)
362 {
363 v >>= 10;
364 t = "KB";
365 }
366 s.Add_UInt64(v);
367 s += t;
368 }
369
370 #ifdef _WIN32
371
TypeToString2(const char * const table[],unsigned num,UInt32 value)372 static AString TypeToString2(const char * const table[], unsigned num, UInt32 value)
373 {
374 char sz[16];
375 const char *p = NULL;
376 if (value < num)
377 p = table[value];
378 if (!p)
379 {
380 ConvertUInt32ToString(value, sz);
381 p = sz;
382 }
383 return (AString)p;
384 }
385
386 // #if defined(Z7_LARGE_PAGES) || defined(_WIN32)
387 // #ifdef _WIN32
PrintSize_KMGT_Or_Hex(AString & s,UInt64 v)388 void PrintSize_KMGT_Or_Hex(AString &s, UInt64 v)
389 {
390 char c = 0;
391 if ((v & 0x3FF) == 0) { v >>= 10; c = 'K';
392 if ((v & 0x3FF) == 0) { v >>= 10; c = 'M';
393 if ((v & 0x3FF) == 0) { v >>= 10; c = 'G';
394 if ((v & 0x3FF) == 0) { v >>= 10; c = 'T';
395 }}}}
396 else
397 {
398 // s += "0x";
399 PrintHex(s, v);
400 return;
401 }
402 s.Add_UInt64(v);
403 if (c)
404 s.Add_Char(c);
405 s.Add_Char('B');
406 }
407 // #endif
408 // #endif
409
SysInfo_To_String(AString & s,const SYSTEM_INFO & si)410 static void SysInfo_To_String(AString &s, const SYSTEM_INFO &si)
411 {
412 s += TypeToString2(k_PROCESSOR_ARCHITECTURE, Z7_ARRAY_SIZE(k_PROCESSOR_ARCHITECTURE), si.wProcessorArchitecture);
413
414 if (!( (si.wProcessorArchitecture == Z7_WIN_PROCESSOR_ARCHITECTURE_INTEL && si.dwProcessorType == Z7_WIN_PROCESSOR_INTEL_PENTIUM)
415 || (si.wProcessorArchitecture == Z7_WIN_PROCESSOR_ARCHITECTURE_AMD64 && si.dwProcessorType == Z7_WIN_PROCESSOR_AMD_X8664)))
416 {
417 s.Add_Space();
418 // s += TypePairToString(k_PROCESSOR, Z7_ARRAY_SIZE(k_PROCESSOR), si.dwProcessorType);
419 s.Add_UInt32(si.dwProcessorType);
420 }
421 s.Add_Space();
422 PrintHex(s, si.wProcessorLevel);
423 s.Add_Dot();
424 PrintHex(s, si.wProcessorRevision);
425 if ((UInt64)si.dwActiveProcessorMask + 1 != ((UInt64)1 << si.dwNumberOfProcessors))
426 if ((UInt64)si.dwActiveProcessorMask + 1 != 0 || si.dwNumberOfProcessors != sizeof(UInt64) * 8)
427 {
428 s += " act:";
429 PrintHex(s, si.dwActiveProcessorMask);
430 }
431 s += " threads:";
432 s.Add_UInt32(si.dwNumberOfProcessors);
433 if (si.dwPageSize != 1 << 12)
434 {
435 s += " page:";
436 PrintPage(s, si.dwPageSize);
437 }
438 if (si.dwAllocationGranularity != 1 << 16)
439 {
440 s += " gran:";
441 PrintPage(s, si.dwAllocationGranularity);
442 }
443 s.Add_Space();
444
445 const DWORD_PTR minAdd = (DWORD_PTR)si.lpMinimumApplicationAddress;
446 UInt64 maxSize = (UInt64)(DWORD_PTR)si.lpMaximumApplicationAddress + 1;
447 const UInt32 kReserveSize = ((UInt32)1 << 16);
448 if (minAdd != kReserveSize)
449 {
450 PrintSize_KMGT_Or_Hex(s, minAdd);
451 s.Add_Minus();
452 }
453 else
454 {
455 if ((maxSize & (kReserveSize - 1)) == 0)
456 maxSize += kReserveSize;
457 }
458 PrintSize_KMGT_Or_Hex(s, maxSize);
459 }
460
461 #ifndef _WIN64
462 EXTERN_C_BEGIN
463 typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
464 EXTERN_C_END
465 #endif
466
467 #endif
468
469 #ifdef __APPLE__
470 #ifndef MY_CPU_X86_OR_AMD64
Add_sysctlbyname_to_String(const char * name,AString & s)471 static void Add_sysctlbyname_to_String(const char *name, AString &s)
472 {
473 size_t bufSize = 256;
474 char buf[256];
475 if (z7_sysctlbyname_Get(name, &buf, &bufSize) == 0)
476 s += buf;
477 }
478 #endif
479 #endif
480
481 void GetSysInfo(AString &s1, AString &s2);
GetSysInfo(AString & s1,AString & s2)482 void GetSysInfo(AString &s1, AString &s2)
483 {
484 s1.Empty();
485 s2.Empty();
486
487 #ifdef _WIN32
488 SYSTEM_INFO si;
489 GetSystemInfo(&si);
490 {
491 SysInfo_To_String(s1, si);
492 // s += " : ";
493 }
494
495 #if !defined(_WIN64) && !defined(UNDER_CE)
496 const
497 Func_GetNativeSystemInfo fn = Z7_GET_PROC_ADDRESS(
498 Func_GetNativeSystemInfo, GetModuleHandleA("kernel32.dll"),
499 "GetNativeSystemInfo");
500 if (fn)
501 {
502 SYSTEM_INFO si2;
503 fn(&si2);
504 // if (memcmp(&si, &si2, sizeof(si)) != 0)
505 {
506 // s += " - ";
507 SysInfo_To_String(s2, si2);
508 }
509 }
510 #endif
511 #endif
512 }
513
514
AddBracedString(AString & dest,AString & src)515 static void AddBracedString(AString &dest, AString &src)
516 {
517 if (!src.IsEmpty())
518 {
519 dest.Add_Space_if_NotEmpty();
520 dest.Add_Char('(');
521 dest += src;
522 dest.Add_Char(')');
523 }
524 }
525
526 struct CCpuName
527 {
528 AString CpuName;
529 AString Revision;
530 AString Microcode;
531 AString LargePages;
532
533 #ifdef _WIN32
534 UInt32 MHz;
535
536 #ifdef MY_CPU_ARM64
537 #define Z7_SYS_INFO_SHOW_ARM64_REGS
538 #endif
539 #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS
540 bool Arm64_ISAR0_EL1_Defined;
541 UInt64 Arm64_ISAR0_EL1;
542 #endif
543 #endif
544
545 #ifdef _WIN32
CCpuNameCCpuName546 CCpuName():
547 MHz(0)
548 #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS
549 , Arm64_ISAR0_EL1_Defined(false)
550 , Arm64_ISAR0_EL1(0)
551 #endif
552 {}
553 #endif
554
555 void Fill();
556
Get_Revision_Microcode_LargePagesCCpuName557 void Get_Revision_Microcode_LargePages(AString &s)
558 {
559 s.Empty();
560 AddBracedString(s, Revision);
561 AddBracedString(s, Microcode);
562 #ifdef _WIN32
563 if (MHz != 0)
564 {
565 s.Add_Space_if_NotEmpty();
566 s.Add_UInt32(MHz);
567 s += " MHz";
568 }
569 #endif
570 if (!LargePages.IsEmpty())
571 s.Add_OptSpaced(LargePages);
572 }
573
574 #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS
Get_RegistersCCpuName575 void Get_Registers(AString &s)
576 {
577 if (Arm64_ISAR0_EL1_Defined)
578 {
579 // ID_AA64ISAR0_EL1
580 s.Add_OptSpaced("cp4030:");
581 PrintHex(s, Arm64_ISAR0_EL1);
582 {
583 const unsigned sha2 = ((unsigned)(Arm64_ISAR0_EL1 >> 12) & 0xf) - 1;
584 if (sha2 < 2)
585 {
586 s += ":SHA256";
587 if (sha2)
588 s += ":SHA512";
589 }
590 }
591 }
592 }
593 #endif
594 };
595
Fill()596 void CCpuName::Fill()
597 {
598 // CpuName.Empty();
599 // Revision.Empty();
600 // Microcode.Empty();
601 // LargePages.Empty();
602
603 AString &s = CpuName;
604
605 #ifdef MY_CPU_X86_OR_AMD64
606 {
607 #if !defined(MY_CPU_AMD64)
608 if (z7_x86_cpuid_GetMaxFunc())
609 #endif
610 {
611 x86cpuid_to_String(s);
612 {
613 UInt32 a[4];
614 z7_x86_cpuid(a, 1);
615 char temp[16];
616 ConvertUInt32ToHex(a[0], temp);
617 Revision += temp;
618 }
619 }
620 }
621 #elif defined(__APPLE__)
622 {
623 Add_sysctlbyname_to_String("machdep.cpu.brand_string", s);
624 }
625 #elif defined(MY_CPU_E2K) && defined(Z7_MCST_LCC_VERSION) && (Z7_MCST_LCC_VERSION >= 12323)
626 {
627 s += "mcst ";
628 s += __builtin_cpu_name();
629 s.Add_Space();
630 s += __builtin_cpu_arch();
631 }
632 #endif
633
634
635 #ifdef _WIN32
636 {
637 NRegistry::CKey key;
638 if (key.Open(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), KEY_READ) == ERROR_SUCCESS)
639 {
640 // s.Empty(); // for debug
641 {
642 CSysString name;
643 if (s.IsEmpty())
644 if (key.QueryValue(TEXT("ProcessorNameString"), name) == ERROR_SUCCESS)
645 {
646 s += GetAnsiString(name);
647 }
648 if (key.QueryValue(TEXT("Identifier"), name) == ERROR_SUCCESS)
649 {
650 if (!Revision.IsEmpty())
651 Revision += " : ";
652 Revision += GetAnsiString(name);
653 }
654 }
655 #ifdef _WIN32
656 key.GetValue_UInt32_IfOk(TEXT("~MHz"), MHz);
657 #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS
658 /*
659 mapping arm64 registers to Windows registry:
660 CP 4000: MIDR_EL1
661 CP 4020: ID_AA64PFR0_EL1
662 CP 4021: ID_AA64PFR1_EL1
663 CP 4028: ID_AA64DFR0_EL1
664 CP 4029: ID_AA64DFR1_EL1
665 CP 402C: ID_AA64AFR0_EL1
666 CP 402D: ID_AA64AFR1_EL1
667 CP 4030: ID_AA64ISAR0_EL1
668 CP 4031: ID_AA64ISAR1_EL1
669 CP 4038: ID_AA64MMFR0_EL1
670 CP 4039: ID_AA64MMFR1_EL1
671 CP 403A: ID_AA64MMFR2_EL1
672 */
673 if (key.GetValue_UInt64_IfOk(TEXT("CP 4030"), Arm64_ISAR0_EL1) == ERROR_SUCCESS)
674 Arm64_ISAR0_EL1_Defined = true;
675 #endif
676 #endif
677 LONG res[2];
678 CByteBuffer bufs[2];
679 res[0] = key.QueryValue_Binary(TEXT("Previous Update Revision"), bufs[0]);
680 res[1] = key.QueryValue_Binary(TEXT("Update Revision"), bufs[1]);
681 if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS)
682 {
683 for (unsigned i = 0; i < 2; i++)
684 {
685 if (i == 1)
686 Microcode += "->";
687 if (res[i] != ERROR_SUCCESS)
688 continue;
689 const CByteBuffer &buf = bufs[i];
690 if (buf.Size() == 8)
691 {
692 const UInt32 high = GetUi32(buf);
693 if (high != 0)
694 {
695 PrintHex(Microcode, high);
696 Microcode.Add_Dot();
697 }
698 PrintHex(Microcode, GetUi32(buf + 4));
699 }
700 }
701 }
702 }
703 }
704 #endif
705
706 if (s.IsEmpty())
707 {
708 #ifdef MY_CPU_NAME
709 s += MY_CPU_NAME;
710 #endif
711 }
712
713 #ifdef __APPLE__
714 {
715 AString s2;
716 UInt32 v = 0;
717 if (z7_sysctlbyname_Get_UInt32("machdep.cpu.core_count", &v) == 0)
718 {
719 s2.Add_UInt32(v);
720 s2.Add_Char('C');
721 }
722 if (z7_sysctlbyname_Get_UInt32("machdep.cpu.thread_count", &v) == 0)
723 {
724 s2.Add_UInt32(v);
725 s2.Add_Char('T');
726 }
727 if (!s2.IsEmpty())
728 {
729 s.Add_Space_if_NotEmpty();
730 s += s2;
731 }
732 }
733 #endif
734
735 #ifdef Z7_LARGE_PAGES
736 Add_LargePages_String(LargePages);
737 #endif
738 }
739
740 void AddCpuFeatures(AString &s);
AddCpuFeatures(AString & s)741 void AddCpuFeatures(AString &s)
742 {
743 #ifdef _WIN32
744 // const unsigned kNumFeatures_Extra = 32; // we check also for unknown features
745 // const unsigned kNumFeatures = Z7_ARRAY_SIZE(k_PF) + kNumFeatures_Extra;
746 const unsigned kNumFeatures = 64;
747 UInt64 flags = 0;
748 for (unsigned i = 0; i < kNumFeatures; i++)
749 {
750 if (IsProcessorFeaturePresent((DWORD)i))
751 {
752 flags += (UInt64)1 << i;
753 // s.Add_Space_if_NotEmpty();
754 // s += TypeToString2(k_PF, Z7_ARRAY_SIZE(k_PF), i);
755 }
756 }
757 s.Add_OptSpaced("f:");
758 PrintHex(s, flags);
759
760 #elif defined(__APPLE__)
761 {
762 UInt32 v = 0;
763 if (z7_sysctlbyname_Get_UInt32("hw.pagesize", &v) == 0)
764 {
765 s.Add_OptSpaced("PageSize:");
766 PrintPage(s, v);
767 }
768 }
769
770 #else
771
772 const long v = sysconf(_SC_PAGESIZE);
773 if (v != -1)
774 {
775 s.Add_OptSpaced("PageSize:");
776 PrintPage(s, (unsigned long)v);
777 }
778
779 #if !defined(_AIX)
780
781 #ifdef __linux__
782
783 CByteBuffer buf;
784 if (ReadFile_to_Buffer("/sys/kernel/mm/transparent_hugepage/enabled", buf))
785 // if (ReadFile_to_Buffer("/proc/cpuinfo", buf))
786 {
787 s.Add_OptSpaced("THP:");
788 AString s2;
789 s2.SetFrom_CalcLen((const char *)(const void *)(const Byte *)buf, (unsigned)buf.Size());
790 const int pos = s2.Find('[');
791 if (pos >= 0)
792 {
793 const int pos2 = s2.Find(']', (unsigned)pos + 1);
794 if (pos2 >= 0)
795 {
796 s2.DeleteFrom((unsigned)pos2);
797 s2.DeleteFrontal((unsigned)pos + 1);
798 }
799 }
800 s += s2;
801 }
802 // else throw CSystemException(MY_SRes_HRESULT_FROM_WRes(errno));
803
804 #endif
805
806
807 #ifdef AT_HWCAP
808 s.Add_OptSpaced("hwcap:");
809 {
810 unsigned long h = MY_getauxval(AT_HWCAP);
811 PrintHex(s, h);
812 #ifdef MY_CPU_ARM64
813 #ifndef HWCAP_SHA3
814 #define HWCAP_SHA3 (1 << 17)
815 #endif
816 #ifndef HWCAP_SHA512
817 #define HWCAP_SHA512 (1 << 21)
818 // #pragma message("=== HWCAP_SHA512 define === ")
819 #endif
820 if (h & HWCAP_CRC32) s += ":CRC32";
821 if (h & HWCAP_SHA1) s += ":SHA1";
822 if (h & HWCAP_SHA2) s += ":SHA2";
823 if (h & HWCAP_SHA3) s += ":SHA3";
824 if (h & HWCAP_SHA512) s += ":SHA512";
825 if (h & HWCAP_AES) s += ":AES";
826 if (h & HWCAP_ASIMD) s += ":ASIMD";
827 #elif defined(MY_CPU_ARM)
828 if (h & HWCAP_NEON) s += ":NEON";
829 #endif
830 }
831 #endif // AT_HWCAP
832
833 #ifdef AT_HWCAP2
834 {
835 unsigned long h = MY_getauxval(AT_HWCAP2);
836 #ifndef MY_CPU_ARM
837 if (h != 0)
838 #endif
839 {
840 s += " hwcap2:";
841 PrintHex(s, h);
842 #ifdef MY_CPU_ARM
843 if (h & HWCAP2_CRC32) s += ":CRC32";
844 if (h & HWCAP2_SHA1) s += ":SHA1";
845 if (h & HWCAP2_SHA2) s += ":SHA2";
846 if (h & HWCAP2_AES) s += ":AES";
847 #endif
848 }
849 }
850 #endif // AT_HWCAP2
851 #endif // _AIX
852 #endif // _WIN32
853 }
854
855
856 #ifdef _WIN32
857 #ifndef UNDER_CE
858
859 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
860
861 EXTERN_C_BEGIN
862 typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
863 EXTERN_C_END
864
My_RtlGetVersion(OSVERSIONINFOEXW * vi)865 static BOOL My_RtlGetVersion(OSVERSIONINFOEXW *vi)
866 {
867 const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
868 if (!ntdll)
869 return FALSE;
870 const
871 Func_RtlGetVersion func = Z7_GET_PROC_ADDRESS(
872 Func_RtlGetVersion, ntdll,
873 "RtlGetVersion");
874 if (!func)
875 return FALSE;
876 func(vi);
877 return TRUE;
878 }
879
880 #endif
881 #endif
882
883
GetOsInfoText(AString & sRes)884 void GetOsInfoText(AString &sRes)
885 {
886 sRes.Empty();
887 AString s;
888
889 #ifdef _WIN32
890 #ifndef UNDER_CE
891 // OSVERSIONINFO vi;
892 OSVERSIONINFOEXW vi;
893 vi.dwOSVersionInfoSize = sizeof(vi);
894 // if (::GetVersionEx(&vi))
895 if (My_RtlGetVersion(&vi))
896 {
897 s += "Windows";
898 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
899 s.Add_UInt32(vi.dwPlatformId);
900 s.Add_Space(); s.Add_UInt32(vi.dwMajorVersion);
901 s.Add_Dot(); s.Add_UInt32(vi.dwMinorVersion);
902 s.Add_Space(); s.Add_UInt32(vi.dwBuildNumber);
903
904 if (vi.wServicePackMajor != 0 || vi.wServicePackMinor != 0)
905 {
906 s += " SP:"; s.Add_UInt32(vi.wServicePackMajor);
907 s.Add_Dot(); s.Add_UInt32(vi.wServicePackMinor);
908 }
909 // s += " Suite:"; PrintHex(s, vi.wSuiteMask);
910 // s += " Type:"; s.Add_UInt32(vi.wProductType);
911 // s.Add_Space(); s += GetOemString(vi.szCSDVersion);
912 }
913 /*
914 {
915 s += " OEMCP:"; s.Add_UInt32(GetOEMCP());
916 s += " ACP:"; s.Add_UInt32(GetACP());
917 }
918 */
919 #endif
920 #else // _WIN32
921
922 if (!s.IsEmpty())
923 s.Add_LF();
924 struct utsname un;
925 if (uname(&un) == 0)
926 {
927 s += un.sysname;
928 // s += " : "; s += un.nodename; // we don't want to show name of computer
929 s += " : "; s += un.release;
930 s += " : "; s += un.version;
931 s += " : "; s += un.machine;
932
933 #ifdef __APPLE__
934 // Add_sysctlbyname_to_String("kern.version", s);
935 // it's same as "utsname.version"
936 #endif
937 }
938 #endif // _WIN32
939
940 sRes += s;
941 #ifdef MY_CPU_X86_OR_AMD64
942 {
943 AString s2;
944 GetVirtCpuid(s2);
945 if (!s2.IsEmpty())
946 {
947 sRes += " : ";
948 sRes += s2;
949 }
950 }
951 #endif
952 }
953
954
955
GetSystemInfoText(AString & sRes)956 void GetSystemInfoText(AString &sRes)
957 {
958 GetOsInfoText(sRes);
959 sRes.Add_LF();
960
961 {
962 AString s, s1, s2;
963 GetSysInfo(s1, s2);
964 if (!s1.IsEmpty() || !s2.IsEmpty())
965 {
966 s = s1;
967 if (s1 != s2 && !s2.IsEmpty())
968 {
969 s += " - ";
970 s += s2;
971 }
972 }
973 {
974 AddCpuFeatures(s);
975 if (!s.IsEmpty())
976 {
977 sRes += s;
978 sRes.Add_LF();
979 }
980 }
981 }
982 {
983 AString s, registers;
984 GetCpuName_MultiLine(s, registers);
985 if (!s.IsEmpty())
986 {
987 sRes += s;
988 sRes.Add_LF();
989 }
990 if (!registers.IsEmpty())
991 {
992 sRes += registers;
993 sRes.Add_LF();
994 }
995 }
996 /*
997 #ifdef MY_CPU_X86_OR_AMD64
998 {
999 AString s;
1000 x86cpuid_all_to_String(s);
1001 if (!s.IsEmpty())
1002 {
1003 printCallback->Print(s);
1004 printCallback->NewLine();
1005 }
1006 }
1007 #endif
1008 */
1009 }
1010
1011
1012 void GetCpuName_MultiLine(AString &s, AString ®isters);
GetCpuName_MultiLine(AString & s,AString & registers)1013 void GetCpuName_MultiLine(AString &s, AString ®isters)
1014 {
1015 CCpuName cpuName;
1016 cpuName.Fill();
1017 s = cpuName.CpuName;
1018 AString s2;
1019 cpuName.Get_Revision_Microcode_LargePages(s2);
1020 if (!s2.IsEmpty())
1021 {
1022 s.Add_LF();
1023 s += s2;
1024 }
1025 registers.Empty();
1026 #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS
1027 cpuName.Get_Registers(registers);
1028 #endif
1029 }
1030
1031
1032 #ifdef MY_CPU_X86_OR_AMD64
1033
GetVirtCpuid(AString & s)1034 void GetVirtCpuid(AString &s)
1035 {
1036 const UInt32 kHv = 0x40000000;
1037
1038 Z7_IF_X86_CPUID_SUPPORTED
1039 {
1040 UInt32 a[4];
1041 z7_x86_cpuid(a, kHv);
1042
1043 if (a[0] < kHv || a[0] >= kHv + (1 << 16))
1044 return;
1045 {
1046 {
1047 for (unsigned j = 1; j < 4; j++)
1048 PrintCpuChars(s, a[j]);
1049 }
1050 }
1051 if (a[0] >= kHv + 1)
1052 {
1053 UInt32 d[4];
1054 z7_x86_cpuid(d, kHv + 1);
1055 s += " : ";
1056 PrintCpuChars(s, d[0]);
1057 if (a[0] >= kHv + 2)
1058 {
1059 z7_x86_cpuid(d, kHv + 2);
1060 s += " : ";
1061 s.Add_UInt32(d[1] >> 16);
1062 s.Add_Dot(); s.Add_UInt32(d[1] & 0xffff);
1063 s.Add_Dot(); s.Add_UInt32(d[0]);
1064 s.Add_Dot(); s.Add_UInt32(d[2]);
1065 s.Add_Dot(); s.Add_UInt32(d[3] >> 24);
1066 s.Add_Dot(); s.Add_UInt32(d[3] & 0xffffff);
1067 }
1068 /*
1069 if (a[0] >= kHv + 5)
1070 {
1071 z7_x86_cpuid(d, kHv + 5);
1072 s += " : ";
1073 s.Add_UInt32(d[0]);
1074 s += "p";
1075 s.Add_UInt32(d[1]);
1076 s += "t";
1077 }
1078 */
1079 }
1080 }
1081 }
1082
1083 #endif
1084
1085
GetCompiler(AString & s)1086 void GetCompiler(AString &s)
1087 {
1088 #ifdef __clang__
1089 s += " CLANG ";
1090 s.Add_UInt32(__clang_major__);
1091 s.Add_Dot();
1092 s.Add_UInt32(__clang_minor__);
1093 s.Add_Dot();
1094 s.Add_UInt32(__clang_patchlevel__);
1095 #endif
1096
1097 #ifdef __xlC__
1098 s += " XLC ";
1099 s.Add_UInt32(__xlC__ >> 8);
1100 s.Add_Dot();
1101 s.Add_UInt32(__xlC__ & 0xFF);
1102 #ifdef __xlC_ver__
1103 s.Add_Dot();
1104 s.Add_UInt32(__xlC_ver__ >> 8);
1105 s.Add_Dot();
1106 s.Add_UInt32(__xlC_ver__ & 0xFF);
1107 #endif
1108 #endif
1109
1110 // #define __LCC__ 126
1111 // #define __LCC_MINOR__ 20
1112 // #define __MCST__ 1
1113 #ifdef __MCST__
1114 s += " MCST";
1115 #endif
1116 #ifdef __LCC__
1117 s += " LCC ";
1118 s.Add_UInt32(__LCC__ / 100);
1119 s.Add_Dot();
1120 s.Add_UInt32(__LCC__ % 100 / 10);
1121 s.Add_UInt32(__LCC__ % 10);
1122 #ifdef __LCC_MINOR__
1123 s.Add_Dot();
1124 s.Add_UInt32(__LCC_MINOR__ / 10);
1125 s.Add_UInt32(__LCC_MINOR__ % 10);
1126 #endif
1127 #endif
1128
1129 // #define __EDG_VERSION__ 602
1130 #ifdef __EDG_VERSION__
1131 s += " EDG ";
1132 s.Add_UInt32(__EDG_VERSION__ / 100);
1133 s.Add_Dot();
1134 s.Add_UInt32(__EDG_VERSION__ % 100 / 10);
1135 s.Add_UInt32(__EDG_VERSION__ % 10);
1136 #endif
1137
1138 #ifdef __VERSION__
1139 s.Add_Space();
1140 s += "ver:";
1141 s += __VERSION__;
1142 #endif
1143
1144 #ifdef __GNUC__
1145 s += " GCC ";
1146 s.Add_UInt32(__GNUC__);
1147 s.Add_Dot();
1148 s.Add_UInt32(__GNUC_MINOR__);
1149 s.Add_Dot();
1150 s.Add_UInt32(__GNUC_PATCHLEVEL__);
1151 #endif
1152
1153
1154 #ifdef _MSC_VER
1155 s += " MSC ";
1156 s.Add_UInt32(_MSC_VER);
1157 #ifdef _MSC_FULL_VER
1158 s.Add_Dot();
1159 s.Add_UInt32(_MSC_FULL_VER);
1160 #endif
1161
1162 #endif
1163
1164 #if defined(__AVX512F__)
1165 #if defined(__AVX512VL__)
1166 #define MY_CPU_COMPILE_ISA "AVX512VL"
1167 #else
1168 #define MY_CPU_COMPILE_ISA "AVX512F"
1169 #endif
1170 #elif defined(__AVX2__)
1171 #define MY_CPU_COMPILE_ISA "AVX2"
1172 #elif defined(__AVX__)
1173 #define MY_CPU_COMPILE_ISA "AVX"
1174 #elif defined(__SSE2__)
1175 #define MY_CPU_COMPILE_ISA "SSE2"
1176 #elif defined(_M_IX86_FP) && (_M_IX86_FP >= 2)
1177 #define MY_CPU_COMPILE_ISA "SSE2"
1178 #elif defined(__SSE__)
1179 #define MY_CPU_COMPILE_ISA "SSE"
1180 #elif defined(_M_IX86_FP) && (_M_IX86_FP >= 1)
1181 #define MY_CPU_COMPILE_ISA "SSE"
1182 #elif defined(__i686__)
1183 #define MY_CPU_COMPILE_ISA "i686"
1184 #elif defined(__i586__)
1185 #define MY_CPU_COMPILE_ISA "i586"
1186 #elif defined(__i486__)
1187 #define MY_CPU_COMPILE_ISA "i486"
1188 #elif defined(__i386__)
1189 #define MY_CPU_COMPILE_ISA "i386"
1190 #elif defined(_M_IX86_FP)
1191 #define MY_CPU_COMPILE_ISA "IA32"
1192 #endif
1193
1194 AString s2;
1195
1196 #ifdef MY_CPU_COMPILE_ISA
1197 s2.Add_OptSpaced(MY_CPU_COMPILE_ISA);
1198 #endif
1199
1200 #ifndef MY_CPU_ARM64
1201 #ifdef __ARM_FP
1202 s2.Add_OptSpaced("FP");
1203 #endif
1204 #ifdef __ARM_NEON
1205 s2.Add_OptSpaced("NEON");
1206 #endif
1207 #ifdef __NEON__
1208 s2.Add_OptSpaced("__NEON__");
1209 #endif
1210 #ifdef __ARM_FEATURE_SIMD32
1211 s2.Add_OptSpaced("SIMD32");
1212 #endif
1213 #endif
1214
1215 #ifdef __ARM_FEATURE_CRYPTO
1216 s2.Add_OptSpaced("CRYPTO");
1217 #endif
1218
1219 #ifdef __ARM_FEATURE_SHA2
1220 s2.Add_OptSpaced("SHA2");
1221 #endif
1222
1223 #ifdef __ARM_FEATURE_AES
1224 s2.Add_OptSpaced("AES");
1225 #endif
1226
1227 #ifdef __ARM_FEATURE_CRC32
1228 s2.Add_OptSpaced("CRC32");
1229 #endif
1230
1231 #ifdef __ARM_FEATURE_UNALIGNED
1232 s2.Add_OptSpaced("UNALIGNED");
1233 #endif
1234
1235
1236 #ifdef MY_CPU_BE
1237 s2.Add_OptSpaced("BE");
1238 #endif
1239
1240 #if defined(MY_CPU_LE_UNALIGN) \
1241 && !defined(MY_CPU_X86_OR_AMD64) \
1242 && !defined(MY_CPU_ARM64)
1243 s2.Add_OptSpaced("LE-unaligned");
1244 #endif
1245
1246 if (!s2.IsEmpty())
1247 {
1248 s.Add_OptSpaced(": ");
1249 s += s2;
1250 }
1251 }
1252