Hardware/CPU/CPUID.cs
author moel.mich
Sun, 23 Sep 2012 18:37:43 +0000
changeset 380 573f1fff48b2
parent 329 756af5ee409e
child 427 39ed1a16c32a
permissions -rw-r--r--
Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
moel@90
     1
/*
moel@90
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@90
     6
 
moel@344
     7
  Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	
moel@90
     9
*/
moel@90
    10
moel@90
    11
using System;
moel@90
    12
using System.Text;
moel@90
    13
moel@90
    14
namespace OpenHardwareMonitor.Hardware.CPU {
moel@165
    15
moel@165
    16
  internal enum Vendor {
moel@90
    17
    Unknown,
moel@90
    18
    Intel,
moel@90
    19
    AMD,
moel@90
    20
  }
moel@165
    21
moel@165
    22
  internal class CPUID {
moel@90
    23
moel@195
    24
    private readonly int thread;
moel@90
    25
moel@195
    26
    private readonly Vendor vendor = Vendor.Unknown;
moel@90
    27
moel@195
    28
    private readonly string cpuBrandString = "";
moel@195
    29
    private readonly string name = "";
moel@90
    30
moel@195
    31
    private readonly uint[,] cpuidData = new uint[0, 0];
moel@195
    32
    private readonly uint[,] cpuidExtData = new uint[0, 0];
moel@90
    33
moel@195
    34
    private readonly uint family;
moel@195
    35
    private readonly uint model;
moel@195
    36
    private readonly uint stepping;
moel@90
    37
moel@195
    38
    private readonly uint apicId;
moel@90
    39
moel@195
    40
    private readonly uint threadMaskWith;
moel@195
    41
    private readonly uint coreMaskWith;
moel@90
    42
moel@195
    43
    private readonly uint processorId;
moel@195
    44
    private readonly uint coreId;
moel@195
    45
    private readonly uint threadId;
moel@90
    46
moel@195
    47
    public const uint CPUID_0 = 0;
moel@195
    48
    public const uint CPUID_EXT = 0x80000000;
moel@90
    49
moel@167
    50
    private static void AppendRegister(StringBuilder b, uint value) {
moel@90
    51
      b.Append((char)((value) & 0xff));
moel@90
    52
      b.Append((char)((value >> 8) & 0xff));
moel@90
    53
      b.Append((char)((value >> 16) & 0xff));
moel@90
    54
      b.Append((char)((value >> 24) & 0xff));
moel@90
    55
    }
moel@90
    56
moel@167
    57
    private static uint NextLog2(long x) {
moel@105
    58
      if (x <= 0)
moel@105
    59
        return 0;
moel@105
    60
moel@105
    61
      x--;
moel@105
    62
      uint count = 0;
moel@105
    63
      while (x > 0) {
moel@105
    64
        x >>= 1;
moel@105
    65
        count++;
moel@105
    66
      }
moel@105
    67
moel@105
    68
      return count;
moel@105
    69
    }
moel@105
    70
moel@90
    71
    public CPUID(int thread) {
moel@90
    72
      this.thread = thread;
moel@90
    73
moel@124
    74
      uint maxCpuid = 0;
moel@124
    75
      uint maxCpuidExt = 0;
moel@124
    76
moel@90
    77
      uint eax, ebx, ecx, edx;
moel@90
    78
moel@112
    79
      if (thread >= 32)
moel@167
    80
        throw new ArgumentOutOfRangeException("thread");
moel@238
    81
      ulong mask = 1UL << thread;
moel@90
    82
moel@236
    83
      if (Opcode.CpuidTx(CPUID_0, 0,
moel@90
    84
          out eax, out ebx, out ecx, out edx, mask)) {
moel@112
    85
        if (eax > 0)
moel@112
    86
          maxCpuid = eax;
moel@112
    87
        else
moel@112
    88
          return;
moel@112
    89
moel@90
    90
        StringBuilder vendorBuilder = new StringBuilder();
moel@90
    91
        AppendRegister(vendorBuilder, ebx);
moel@90
    92
        AppendRegister(vendorBuilder, edx);
moel@90
    93
        AppendRegister(vendorBuilder, ecx);
moel@90
    94
        string cpuVendor = vendorBuilder.ToString();
moel@90
    95
        switch (cpuVendor) {
moel@90
    96
          case "GenuineIntel":
moel@90
    97
            vendor = Vendor.Intel;
moel@90
    98
            break;
moel@90
    99
          case "AuthenticAMD":
moel@90
   100
            vendor = Vendor.AMD;
moel@90
   101
            break;
moel@90
   102
          default:
moel@90
   103
            vendor = Vendor.Unknown;
moel@90
   104
            break;
moel@90
   105
        }
moel@90
   106
        eax = ebx = ecx = edx = 0;
moel@236
   107
        if (Opcode.CpuidTx(CPUID_EXT, 0,
moel@112
   108
          out eax, out ebx, out ecx, out edx, mask)) {
moel@112
   109
          if (eax > CPUID_EXT)
moel@112
   110
            maxCpuidExt = eax - CPUID_EXT;
moel@112
   111
          else
moel@112
   112
            return;
moel@124
   113
        } else {
moel@167
   114
          throw new ArgumentOutOfRangeException("thread");
moel@112
   115
        }
moel@90
   116
      } else {
moel@167
   117
        throw new ArgumentOutOfRangeException("thread");
moel@90
   118
      }
moel@90
   119
moel@112
   120
      maxCpuid = Math.Min(maxCpuid, 1024);
moel@112
   121
      maxCpuidExt = Math.Min(maxCpuidExt, 1024);   
moel@90
   122
moel@90
   123
      cpuidData = new uint[maxCpuid + 1, 4];
moel@90
   124
      for (uint i = 0; i < (maxCpuid + 1); i++)
moel@236
   125
        Opcode.CpuidTx(CPUID_0 + i, 0, 
moel@90
   126
          out cpuidData[i, 0], out cpuidData[i, 1],
moel@90
   127
          out cpuidData[i, 2], out cpuidData[i, 3], mask);
moel@90
   128
moel@95
   129
      cpuidExtData = new uint[maxCpuidExt + 1, 4];
moel@95
   130
      for (uint i = 0; i < (maxCpuidExt + 1); i++)
moel@236
   131
        Opcode.CpuidTx(CPUID_EXT + i, 0, 
moel@90
   132
          out cpuidExtData[i, 0], out cpuidExtData[i, 1], 
moel@90
   133
          out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask);
moel@90
   134
moel@90
   135
      StringBuilder nameBuilder = new StringBuilder();
moel@90
   136
      for (uint i = 2; i <= 4; i++) {
moel@236
   137
        if (Opcode.CpuidTx(CPUID_EXT + i, 0, 
moel@90
   138
          out eax, out ebx, out ecx, out edx, mask)) 
moel@90
   139
        {
moel@90
   140
          AppendRegister(nameBuilder, eax);
moel@90
   141
          AppendRegister(nameBuilder, ebx);
moel@90
   142
          AppendRegister(nameBuilder, ecx);
moel@90
   143
          AppendRegister(nameBuilder, edx);
moel@90
   144
        }
moel@90
   145
      }
moel@90
   146
      nameBuilder.Replace('\0', ' ');
moel@90
   147
      cpuBrandString = nameBuilder.ToString().Trim();
moel@90
   148
      nameBuilder.Replace("(R)", " ");
moel@90
   149
      nameBuilder.Replace("(TM)", " ");
moel@329
   150
      nameBuilder.Replace("(tm)", "");
moel@90
   151
      nameBuilder.Replace("CPU", "");
moel@329
   152
      nameBuilder.Replace("Quad-Core Processor", "");
moel@329
   153
      nameBuilder.Replace("Six-Core Processor", "");
moel@329
   154
      nameBuilder.Replace("Eight-Core Processor", "");
moel@90
   155
      for (int i = 0; i < 10; i++) nameBuilder.Replace("  ", " ");
moel@90
   156
      name = nameBuilder.ToString();
moel@90
   157
      if (name.Contains("@"))
moel@90
   158
        name = name.Remove(name.LastIndexOf('@'));
moel@95
   159
      name = name.Trim();      
moel@90
   160
moel@90
   161
      this.family = ((cpuidData[1, 0] & 0x0FF00000) >> 20) +
moel@90
   162
        ((cpuidData[1, 0] & 0x0F00) >> 8);
moel@90
   163
      this.model = ((cpuidData[1, 0] & 0x0F0000) >> 12) +
moel@90
   164
        ((cpuidData[1, 0] & 0xF0) >> 4);
moel@90
   165
      this.stepping = (cpuidData[1, 0] & 0x0F);
moel@90
   166
moel@90
   167
      this.apicId = (cpuidData[1, 1] >> 24) & 0xFF;
moel@90
   168
moel@90
   169
      switch (vendor) {
moel@90
   170
        case Vendor.Intel:
moel@90
   171
          uint maxCoreAndThreadIdPerPackage = (cpuidData[1, 1] >> 16) & 0xFF;
moel@95
   172
          uint maxCoreIdPerPackage;
moel@95
   173
          if (maxCpuid >= 4)
moel@95
   174
            maxCoreIdPerPackage = ((cpuidData[4, 0] >> 26) & 0x3F) + 1;
moel@95
   175
          else
moel@95
   176
            maxCoreIdPerPackage = 1;
moel@105
   177
          threadMaskWith = 
moel@105
   178
            NextLog2(maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage);
moel@105
   179
          coreMaskWith = NextLog2(maxCoreIdPerPackage);
moel@90
   180
          break;
moel@90
   181
        case Vendor.AMD:
moel@95
   182
          uint corePerPackage;
moel@95
   183
          if (maxCpuidExt >= 8)
moel@95
   184
            corePerPackage = (cpuidExtData[8, 2] & 0xFF) + 1;
moel@95
   185
          else
moel@95
   186
            corePerPackage = 1;
moel@90
   187
          threadMaskWith = 0;
moel@105
   188
          coreMaskWith = NextLog2(corePerPackage);
moel@90
   189
          break;
moel@90
   190
        default:
moel@90
   191
          threadMaskWith = 0;
moel@90
   192
          coreMaskWith = 0;
moel@90
   193
          break;
moel@90
   194
      }
moel@90
   195
moel@195
   196
      processorId = (apicId >> (int)(coreMaskWith + threadMaskWith));
moel@195
   197
      coreId = ((apicId >> (int)(threadMaskWith)) 
moel@102
   198
        - (processorId << (int)(coreMaskWith)));
moel@95
   199
      threadId = apicId
moel@95
   200
        - (processorId << (int)(coreMaskWith + threadMaskWith))
moel@95
   201
        - (coreId << (int)(threadMaskWith)); 
moel@90
   202
    }
moel@90
   203
moel@90
   204
    public string Name {
moel@90
   205
      get { return name; }
moel@90
   206
    }
moel@90
   207
moel@90
   208
    public string BrandString {
moel@90
   209
      get { return cpuBrandString; }
moel@90
   210
    }
moel@90
   211
moel@90
   212
    public int Thread {
moel@90
   213
      get { return thread; }
moel@90
   214
    }
moel@90
   215
moel@90
   216
    public Vendor Vendor {
moel@90
   217
      get { return vendor; }
moel@90
   218
    }
moel@90
   219
moel@90
   220
    public uint Family {
moel@90
   221
      get { return family; }
moel@90
   222
    }
moel@90
   223
moel@90
   224
    public uint Model {
moel@90
   225
      get { return model; }
moel@90
   226
    }
moel@90
   227
moel@90
   228
    public uint Stepping {
moel@90
   229
      get { return stepping; }
moel@90
   230
    }
moel@90
   231
moel@90
   232
    public uint ApicId {
moel@90
   233
      get { return apicId; }
moel@90
   234
    }
moel@90
   235
moel@90
   236
    public uint ProcessorId {
moel@90
   237
      get { return processorId; }
moel@90
   238
    }
moel@90
   239
moel@90
   240
    public uint CoreId {
moel@90
   241
      get { return coreId; }
moel@90
   242
    }
moel@90
   243
moel@90
   244
    public uint ThreadId {
moel@90
   245
      get { return threadId; }
moel@90
   246
    }
moel@90
   247
moel@90
   248
    public uint[,] Data {
moel@90
   249
      get { return cpuidData; }
moel@90
   250
    }
moel@90
   251
moel@90
   252
    public uint[,] ExtData {
moel@90
   253
      get { return cpuidExtData; }
moel@90
   254
    }
moel@90
   255
  }
moel@90
   256
}