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