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.
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/.
7 Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
8 Copyright (C) 2010 Paul Werelds <paul@werelds.net>
13 using System.Globalization;
15 using System.Threading;
17 namespace OpenHardwareMonitor.Hardware.CPU {
18 internal sealed class AMD0FCPU : AMDCPU {
20 private readonly Sensor[] coreTemperatures;
21 private readonly Sensor[] coreClocks;
22 private readonly Sensor busClock;
24 private const uint FIDVID_STATUS = 0xC0010042;
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;
30 private readonly byte thermSenseCoreSelCPU0;
31 private readonly byte thermSenseCoreSelCPU1;
32 private readonly uint miscellaneousControlAddress;
34 public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
35 : base(processorIndex, cpuid, settings)
37 float offset = -49.0f;
39 // AM2+ 65nm +21 offset
40 uint model = cpuid[0][0].Model;
41 if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c)
45 // AMD Athlon 64 Processors
46 thermSenseCoreSelCPU0 = 0x0;
47 thermSenseCoreSelCPU1 = 0x4;
49 // AMD NPT Family 0Fh Revision F, G have the core selection swapped
50 thermSenseCoreSelCPU0 = 0x4;
51 thermSenseCoreSelCPU1 = 0x0;
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)
58 coreTemperatures = new Sensor[coreCount];
59 for (int i = 0; i < coreCount; 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)
68 coreTemperatures = new Sensor[0];
71 miscellaneousControlAddress = GetPciAddress(
72 MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
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,
79 if (HasTimeStampCounter)
80 ActivateSensor(coreClocks[i]);
86 protected override uint[] GetMSRs() {
87 return new [] { FIDVID_STATUS };
90 public override string GetReport() {
91 StringBuilder r = new StringBuilder();
92 r.Append(base.GetReport());
94 r.Append("Miscellaneous Control Address: 0x");
95 r.AppendLine((miscellaneousControlAddress).ToString("X",
96 CultureInfo.InvariantCulture));
102 public override void Update() {
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)) {
111 if (Ring0.ReadPciConfig(
112 miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
115 coreTemperatures[i].Value = ((value >> 16) & 0xFF) +
116 coreTemperatures[i].Parameters[0].Value;
117 ActivateSensor(coreTemperatures[i]);
119 DeactivateSensor(coreTemperatures[i]);
125 if (HasTimeStampCounter) {
126 double newBusClock = 0;
128 for (int i = 0; i < coreClocks.Length; i++) {
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);
142 // Fail-safe value - if the code above fails, we'll use this instead
143 coreClocks[i].Value = (float)TimeStampCounterFrequency;
147 if (newBusClock > 0) {
148 this.busClock.Value = (float)newBusClock;
149 ActivateSensor(this.busClock);