xref: /aosp_15_r20/external/lzma/CPP/Windows/SystemInfo.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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 &registers);
GetCpuName_MultiLine(AString & s,AString & registers)1013 void GetCpuName_MultiLine(AString &s, AString &registers)
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