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