xref: /third_party/lzma/CPP/Windows/SystemInfo.cpp (revision 370b324c)
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
53using namespace NWindows;
54
55#ifdef __linux__
56
57static 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)
95static 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
105Z7_NO_INLINE
106static 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
128static 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/*
161static 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
204static 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/*
230static 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/*
266static 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
310static 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
324static 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
340void 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
362static 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
414EXTERN_C_BEGIN
415typedef VOID (WINAPI *Func_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
416EXTERN_C_END
417#endif
418
419#endif
420
421#ifdef __APPLE__
422#ifndef MY_CPU_X86_OR_AMD64
423static 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
433void GetSysInfo(AString &s1, AString &s2);
434void 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
467void GetCpuName(AString &s);
468
469static 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
481struct CCpuName
482{
483  AString CpuName;
484  AString Revision;
485  AString Microcode;
486  AString LargePages;
487
488  void Fill();
489
490  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
499void 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
615void AddCpuFeatures(AString &s);
616void 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
725EXTERN_C_BEGIN
726typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
727EXTERN_C_END
728
729static 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
748void 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
820void 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
871void GetCpuName(AString &s);
872void 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
883void GetCpuName_MultiLine(AString &s);
884void 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
901void 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
953void 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