• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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