tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CpuArch.c (4339B)


      1 /* CpuArch.c -- CPU specific code
      2 2016-02-25: Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 #include "CpuArch.h"
      7 
      8 #ifdef MY_CPU_X86_OR_AMD64
      9 
     10 #if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
     11 #define USE_ASM
     12 #endif
     13 
     14 #if !defined(USE_ASM) && _MSC_VER >= 1500
     15 #include <intrin.h>
     16 #endif
     17 
     18 #if defined(USE_ASM) && !defined(MY_CPU_AMD64)
     19 static UInt32 CheckFlag(UInt32 flag)
     20 {
     21  #ifdef _MSC_VER
     22  __asm pushfd;
     23  __asm pop EAX;
     24  __asm mov EDX, EAX;
     25  __asm xor EAX, flag;
     26  __asm push EAX;
     27  __asm popfd;
     28  __asm pushfd;
     29  __asm pop EAX;
     30  __asm xor EAX, EDX;
     31  __asm push EDX;
     32  __asm popfd;
     33  __asm and flag, EAX;
     34  #else
     35  __asm__ __volatile__ (
     36    "pushf\n\t"
     37    "pop  %%EAX\n\t"
     38    "movl %%EAX,%%EDX\n\t"
     39    "xorl %0,%%EAX\n\t"
     40    "push %%EAX\n\t"
     41    "popf\n\t"
     42    "pushf\n\t"
     43    "pop  %%EAX\n\t"
     44    "xorl %%EDX,%%EAX\n\t"
     45    "push %%EDX\n\t"
     46    "popf\n\t"
     47    "andl %%EAX, %0\n\t":
     48    "=c" (flag) : "c" (flag) :
     49    "%eax", "%edx");
     50  #endif
     51  return flag;
     52 }
     53 #define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
     54 #else
     55 #define CHECK_CPUID_IS_SUPPORTED
     56 #endif
     57 
     58 void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
     59 {
     60  #ifdef USE_ASM
     61 
     62  #ifdef _MSC_VER
     63 
     64  UInt32 a2, b2, c2, d2;
     65  __asm xor EBX, EBX;
     66  __asm xor ECX, ECX;
     67  __asm xor EDX, EDX;
     68  __asm mov EAX, function;
     69  __asm cpuid;
     70  __asm mov a2, EAX;
     71  __asm mov b2, EBX;
     72  __asm mov c2, ECX;
     73  __asm mov d2, EDX;
     74 
     75  *a = a2;
     76  *b = b2;
     77  *c = c2;
     78  *d = d2;
     79 
     80  #else
     81 
     82  __asm__ __volatile__ (
     83  #if defined(MY_CPU_AMD64) && defined(__PIC__)
     84    "mov %%rbx, %%rdi;"
     85    "cpuid;"
     86    "xchg %%rbx, %%rdi;"
     87    : "=a" (*a) ,
     88      "=D" (*b) ,
     89  #elif defined(MY_CPU_X86) && defined(__PIC__)
     90    "mov %%ebx, %%edi;"
     91    "cpuid;"
     92    "xchgl %%ebx, %%edi;"
     93    : "=a" (*a) ,
     94      "=D" (*b) ,
     95  #else
     96    "cpuid"
     97    : "=a" (*a) ,
     98      "=b" (*b) ,
     99  #endif
    100      "=c" (*c) ,
    101      "=d" (*d)
    102    : "0" (function)) ;
    103 
    104  #endif
    105  
    106  #else
    107 
    108  int CPUInfo[4];
    109  __cpuid(CPUInfo, function);
    110  *a = CPUInfo[0];
    111  *b = CPUInfo[1];
    112  *c = CPUInfo[2];
    113  *d = CPUInfo[3];
    114 
    115  #endif
    116 }
    117 
    118 Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
    119 {
    120  CHECK_CPUID_IS_SUPPORTED
    121  MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
    122  MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
    123  return True;
    124 }
    125 
    126 static const UInt32 kVendors[][3] =
    127 {
    128  { 0x756E6547, 0x49656E69, 0x6C65746E},
    129  { 0x68747541, 0x69746E65, 0x444D4163},
    130  { 0x746E6543, 0x48727561, 0x736C7561}
    131 };
    132 
    133 int x86cpuid_GetFirm(const Cx86cpuid *p)
    134 {
    135  unsigned i;
    136  for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
    137  {
    138    const UInt32 *v = kVendors[i];
    139    if (v[0] == p->vendor[0] &&
    140        v[1] == p->vendor[1] &&
    141        v[2] == p->vendor[2])
    142      return (int)i;
    143  }
    144  return -1;
    145 }
    146 
    147 Bool CPU_Is_InOrder()
    148 {
    149  Cx86cpuid p;
    150  int firm;
    151  UInt32 family, model;
    152  if (!x86cpuid_CheckAndRead(&p))
    153    return True;
    154 
    155  family = x86cpuid_GetFamily(p.ver);
    156  model = x86cpuid_GetModel(p.ver);
    157  
    158  firm = x86cpuid_GetFirm(&p);
    159 
    160  switch (firm)
    161  {
    162    case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
    163        /* In-Order Atom CPU */
    164           model == 0x1C  /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
    165        || model == 0x26  /* 45 nm, Z6xx */
    166        || model == 0x27  /* 32 nm, Z2460 */
    167        || model == 0x35  /* 32 nm, Z2760 */
    168        || model == 0x36  /* 32 nm, N2xxx, D2xxx */
    169        )));
    170    case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
    171    case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
    172  }
    173  return True;
    174 }
    175 
    176 #if !defined(MY_CPU_AMD64) && defined(_WIN32)
    177 #include <windows.h>
    178 static Bool CPU_Sys_Is_SSE_Supported()
    179 {
    180  OSVERSIONINFO vi;
    181  vi.dwOSVersionInfoSize = sizeof(vi);
    182  if (!GetVersionEx(&vi))
    183    return False;
    184  return (vi.dwMajorVersion >= 5);
    185 }
    186 #define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
    187 #else
    188 #define CHECK_SYS_SSE_SUPPORT
    189 #endif
    190 
    191 Bool CPU_Is_Aes_Supported()
    192 {
    193  Cx86cpuid p;
    194  CHECK_SYS_SSE_SUPPORT
    195  if (!x86cpuid_CheckAndRead(&p))
    196    return False;
    197  return (p.c >> 25) & 1;
    198 }
    199 
    200 #endif