Hardware/CPU/AMD0FCPU.cs
author moel.mich
Sun, 23 Sep 2012 18:37:43 +0000
changeset 380 573f1fff48b2
parent 272 037a2d66082f
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.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
     8   Copyright (C) 2010 Paul Werelds <paul@werelds.net>
     9 
    10 */
    11 
    12 using System;
    13 using System.Globalization;
    14 using System.Text;
    15 using System.Threading;
    16 
    17 namespace OpenHardwareMonitor.Hardware.CPU {
    18   internal sealed class AMD0FCPU : AMDCPU {
    19     
    20     private readonly Sensor[] coreTemperatures;
    21     private readonly Sensor[] coreClocks;
    22     private readonly Sensor busClock;
    23 
    24     private const uint FIDVID_STATUS = 0xC0010042;
    25 
    26     private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
    27     private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1103;
    28     private const uint THERMTRIP_STATUS_REGISTER = 0xE4;
    29     
    30     private readonly byte thermSenseCoreSelCPU0;
    31     private readonly byte thermSenseCoreSelCPU1;
    32     private readonly uint miscellaneousControlAddress;
    33 
    34     public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    35       : base(processorIndex, cpuid, settings) 
    36     {
    37       float offset = -49.0f;
    38 
    39       // AM2+ 65nm +21 offset
    40       uint model = cpuid[0][0].Model;
    41       if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c) 
    42         offset += 21;
    43 
    44       if (model < 40) {
    45         // AMD Athlon 64 Processors
    46         thermSenseCoreSelCPU0 = 0x0;
    47         thermSenseCoreSelCPU1 = 0x4;
    48       } else {
    49         // AMD NPT Family 0Fh Revision F, G have the core selection swapped
    50         thermSenseCoreSelCPU0 = 0x4;
    51         thermSenseCoreSelCPU1 = 0x0;
    52       }
    53 
    54       // check if processor supports a digital thermal sensor 
    55       if (cpuid[0][0].ExtData.GetLength(0) > 7 && 
    56         (cpuid[0][0].ExtData[7, 3] & 1) != 0) 
    57       {
    58         coreTemperatures = new Sensor[coreCount];
    59         for (int i = 0; i < coreCount; i++) {
    60           coreTemperatures[i] =
    61             new Sensor("Core #" + (i + 1), i, SensorType.Temperature,
    62               this, new [] { new ParameterDescription("Offset [°C]", 
    63                   "Temperature offset of the thermal sensor.\n" + 
    64                   "Temperature = Value + Offset.", offset)
    65           }, settings);
    66         }
    67       } else {
    68         coreTemperatures = new Sensor[0];
    69       }
    70 
    71       miscellaneousControlAddress = GetPciAddress(
    72         MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
    73 
    74       busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
    75       coreClocks = new Sensor[coreCount];
    76       for (int i = 0; i < coreClocks.Length; i++) {
    77         coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
    78           this, settings);
    79         if (HasTimeStampCounter)
    80           ActivateSensor(coreClocks[i]);
    81       }
    82 
    83       Update();                   
    84     }
    85 
    86     protected override uint[] GetMSRs() {
    87       return new [] { FIDVID_STATUS };
    88     }
    89 
    90     public override string GetReport() {
    91       StringBuilder r = new StringBuilder();
    92       r.Append(base.GetReport());
    93 
    94       r.Append("Miscellaneous Control Address: 0x");
    95       r.AppendLine((miscellaneousControlAddress).ToString("X", 
    96         CultureInfo.InvariantCulture));
    97       r.AppendLine();
    98 
    99       return r.ToString();
   100     }
   101 
   102     public override void Update() {
   103       base.Update();
   104 
   105       if (miscellaneousControlAddress != Ring0.InvalidPciAddress) {
   106         for (uint i = 0; i < coreTemperatures.Length; i++) {
   107           if (Ring0.WritePciConfig(
   108             miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
   109             i > 0 ? thermSenseCoreSelCPU1 : thermSenseCoreSelCPU0)) {
   110             uint value;
   111             if (Ring0.ReadPciConfig(
   112               miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, 
   113               out value)) 
   114             {
   115               coreTemperatures[i].Value = ((value >> 16) & 0xFF) + 
   116                 coreTemperatures[i].Parameters[0].Value;
   117               ActivateSensor(coreTemperatures[i]);
   118             } else {
   119               DeactivateSensor(coreTemperatures[i]);
   120             }
   121           }
   122         }
   123       }
   124 
   125       if (HasTimeStampCounter) {
   126         double newBusClock = 0;
   127 
   128         for (int i = 0; i < coreClocks.Length; i++) {
   129           Thread.Sleep(1);
   130 
   131           uint eax, edx;
   132           if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx,
   133             1UL << cpuid[i][0].Thread)) {
   134             // CurrFID can be found in eax bits 0-5, MaxFID in 16-21
   135             // 8-13 hold StartFID, we don't use that here.
   136             double curMP = 0.5 * ((eax & 0x3F) + 8);
   137             double maxMP = 0.5 * ((eax >> 16 & 0x3F) + 8);
   138             coreClocks[i].Value = 
   139               (float)(curMP * TimeStampCounterFrequency / maxMP);
   140             newBusClock = (float)(TimeStampCounterFrequency / maxMP);
   141           } else {
   142             // Fail-safe value - if the code above fails, we'll use this instead
   143             coreClocks[i].Value = (float)TimeStampCounterFrequency;
   144           }
   145         }
   146 
   147         if (newBusClock > 0) {
   148           this.busClock.Value = (float)newBusClock;
   149           ActivateSensor(this.busClock);
   150         }
   151       }
   152     }  
   153  
   154   }
   155 }