Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
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-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Collections.Generic;
13 using System.Diagnostics;
14 using System.Globalization;
17 using System.Threading;
19 namespace OpenHardwareMonitor.Hardware.CPU {
21 internal sealed class AMD10CPU : AMDCPU {
23 private readonly Sensor coreTemperature;
24 private readonly Sensor[] coreClocks;
25 private readonly Sensor busClock;
27 private const uint PERF_CTL_0 = 0xC0010000;
28 private const uint PERF_CTR_0 = 0xC0010004;
29 private const uint HWCR = 0xC0010015;
30 private const uint P_STATE_0 = 0xC0010064;
31 private const uint COFVID_STATUS = 0xC0010071;
33 private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
34 private const ushort FAMILY_10H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
35 private const ushort FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1303;
36 private const ushort FAMILY_12H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
37 private const ushort FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
38 private const ushort FAMILY_15H_MODEL_00_MISC_CONTROL_DEVICE_ID = 0x1603;
39 private const ushort FAMILY_15H_MODEL_10_MISC_CONTROL_DEVICE_ID = 0x1403;
40 private const ushort FAMILY_16H_MODEL_00_MISC_CONTROL_DEVICE_ID = 0x1533;
42 private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
43 private const uint CLOCK_POWER_TIMING_CONTROL_0_REGISTER = 0xD4;
45 private readonly uint miscellaneousControlAddress;
46 private readonly ushort miscellaneousControlDeviceId;
48 private readonly FileStream temperatureStream;
50 private readonly double timeStampCounterMultiplier;
51 private readonly bool corePerformanceBoostSupport;
53 public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
54 : base(processorIndex, cpuid, settings)
56 // AMD family 1Xh processors support only one temperature sensor
57 coreTemperature = new Sensor(
58 "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0,
59 SensorType.Temperature, this, new [] {
60 new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
64 case 0x10: miscellaneousControlDeviceId =
65 FAMILY_10H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
66 case 0x11: miscellaneousControlDeviceId =
67 FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
68 case 0x12: miscellaneousControlDeviceId =
69 FAMILY_12H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
70 case 0x14: miscellaneousControlDeviceId =
71 FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
73 switch (model & 0xF0) {
74 case 0x00: miscellaneousControlDeviceId =
75 FAMILY_15H_MODEL_00_MISC_CONTROL_DEVICE_ID; break;
76 case 0x10: miscellaneousControlDeviceId =
77 FAMILY_15H_MODEL_10_MISC_CONTROL_DEVICE_ID; break;
78 default: miscellaneousControlDeviceId = 0; break;
81 switch (model & 0xF0) {
82 case 0x00: miscellaneousControlDeviceId =
83 FAMILY_16H_MODEL_00_MISC_CONTROL_DEVICE_ID; break;
84 default: miscellaneousControlDeviceId = 0; break;
86 default: miscellaneousControlDeviceId = 0; break;
89 // get the pci address for the Miscellaneous Control registers
90 miscellaneousControlAddress = GetPciAddress(
91 MISCELLANEOUS_CONTROL_FUNCTION, miscellaneousControlDeviceId);
93 busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
94 coreClocks = new Sensor[coreCount];
95 for (int i = 0; i < coreClocks.Length; i++) {
96 coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
98 if (HasTimeStampCounter)
99 ActivateSensor(coreClocks[i]);
102 corePerformanceBoostSupport = (cpuid[0][0].ExtData[7, 3] & (1 << 9)) > 0;
104 // set affinity to the first thread for all frequency estimations
105 ulong mask = ThreadAffinity.Set(1UL << cpuid[0][0].Thread);
107 // disable core performance boost
108 uint hwcrEax, hwcrEdx;
109 Ring0.Rdmsr(HWCR, out hwcrEax, out hwcrEdx);
110 if (corePerformanceBoostSupport)
111 Ring0.Wrmsr(HWCR, hwcrEax | (1 << 25), hwcrEdx);
114 Ring0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx);
116 Ring0.Rdmsr(PERF_CTR_0, out ctrEax, out ctrEdx);
118 timeStampCounterMultiplier = estimateTimeStampCounterMultiplier();
120 // restore the performance counter registers
121 Ring0.Wrmsr(PERF_CTL_0, ctlEax, ctlEdx);
122 Ring0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx);
124 // restore core performance boost
125 if (corePerformanceBoostSupport)
126 Ring0.Wrmsr(HWCR, hwcrEax, hwcrEdx);
128 // restore the thread affinity.
129 ThreadAffinity.Set(mask);
131 // the file reader for lm-sensors support on Linux
132 temperatureStream = null;
133 int p = (int)Environment.OSVersion.Platform;
134 if ((p == 4) || (p == 128)) {
135 string[] devicePaths = Directory.GetDirectories("/sys/class/hwmon/");
136 foreach (string path in devicePaths) {
139 using (StreamReader reader = new StreamReader(path + "/device/name"))
140 name = reader.ReadLine();
141 } catch (IOException) { }
144 temperatureStream = new FileStream(path + "/device/temp1_input",
145 FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
154 private double estimateTimeStampCounterMultiplier() {
155 // preload the function
156 estimateTimeStampCounterMultiplier(0);
157 estimateTimeStampCounterMultiplier(0);
159 // estimate the multiplier
160 List<double> estimate = new List<double>(3);
161 for (int i = 0; i < 3; i++)
162 estimate.Add(estimateTimeStampCounterMultiplier(0.025));
167 private double estimateTimeStampCounterMultiplier(double timeWindow) {
170 // select event "076h CPU Clocks not Halted" and enable the counter
171 Ring0.Wrmsr(PERF_CTL_0,
172 (1 << 22) | // enable performance counter
173 (1 << 17) | // count events in user mode
174 (1 << 16) | // count events in operating-system mode
177 // set the counter to 0
178 Ring0.Wrmsr(PERF_CTR_0, 0, 0);
180 long ticks = (long)(timeWindow * Stopwatch.Frequency);
181 uint lsbBegin, msbBegin, lsbEnd, msbEnd;
183 long timeBegin = Stopwatch.GetTimestamp() +
184 (long)Math.Ceiling(0.001 * ticks);
185 long timeEnd = timeBegin + ticks;
186 while (Stopwatch.GetTimestamp() < timeBegin) { }
187 Ring0.Rdmsr(PERF_CTR_0, out lsbBegin, out msbBegin);
189 while (Stopwatch.GetTimestamp() < timeEnd) { }
190 Ring0.Rdmsr(PERF_CTR_0, out lsbEnd, out msbEnd);
191 Ring0.Rdmsr(COFVID_STATUS, out eax, out edx);
192 double coreMultiplier = GetCoreMultiplier(eax);
194 ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
195 ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
197 double coreFrequency = 1e-6 *
198 (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
199 (timeEnd - timeBegin);
201 double busFrequency = coreFrequency / coreMultiplier;
203 return 0.25 * Math.Round(4 * TimeStampCounterFrequency / busFrequency);
206 protected override uint[] GetMSRs() {
207 return new uint[] { PERF_CTL_0, PERF_CTR_0, HWCR, P_STATE_0,
211 public override string GetReport() {
212 StringBuilder r = new StringBuilder();
213 r.Append(base.GetReport());
215 r.Append("Miscellaneous Control Address: 0x");
216 r.AppendLine((miscellaneousControlAddress).ToString("X",
217 CultureInfo.InvariantCulture));
218 r.Append("Time Stamp Counter Multiplier: ");
219 r.AppendLine(timeStampCounterMultiplier.ToString(
220 CultureInfo.InvariantCulture));
221 if (family == 0x14) {
223 Ring0.ReadPciConfig(miscellaneousControlAddress,
224 CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
225 r.Append("PCI Register D18F3xD4: ");
226 r.AppendLine(value.ToString("X8", CultureInfo.InvariantCulture));
233 private double GetCoreMultiplier(uint cofvidEax) {
239 // 8:6 CpuDid: current core divisor ID
240 // 5:0 CpuFid: current core frequency ID
241 uint cpuDid = (cofvidEax >> 6) & 7;
242 uint cpuFid = cofvidEax & 0x1F;
243 return 0.5 * (cpuFid + 0x10) / (1 << (int)cpuDid);
246 // 8:4 CpuFid: current CPU core frequency ID
247 // 3:0 CpuDid: current CPU core divisor ID
248 uint cpuFid = (cofvidEax >> 4) & 0x1F;
249 uint cpuDid = cofvidEax & 0xF;
252 case 0: divisor = 1; break;
253 case 1: divisor = 1.5; break;
254 case 2: divisor = 2; break;
255 case 3: divisor = 3; break;
256 case 4: divisor = 4; break;
257 case 5: divisor = 6; break;
258 case 6: divisor = 8; break;
259 case 7: divisor = 12; break;
260 case 8: divisor = 16; break;
261 default: divisor = 1; break;
263 return (cpuFid + 0x10) / divisor;
266 // 8:4: current CPU core divisor ID most significant digit
267 // 3:0: current CPU core divisor ID least significant digit
268 uint divisorIdMSD = (cofvidEax >> 4) & 0x1F;
269 uint divisorIdLSD = cofvidEax & 0xF;
271 Ring0.ReadPciConfig(miscellaneousControlAddress,
272 CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
273 uint frequencyId = value & 0x1F;
274 return (frequencyId + 0x10) /
275 (divisorIdMSD + (divisorIdLSD * 0.25) + 1);
282 private string ReadFirstLine(Stream stream) {
283 StringBuilder sb = new StringBuilder();
285 stream.Seek(0, SeekOrigin.Begin);
286 int b = stream.ReadByte();
287 while (b != -1 && b != 10) {
289 b = stream.ReadByte();
292 return sb.ToString();
295 public override void Update() {
298 if (temperatureStream == null) {
299 if (miscellaneousControlAddress != Ring0.InvalidPciAddress) {
301 if (Ring0.ReadPciConfig(miscellaneousControlAddress,
302 REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) {
303 if (family == 0x15 && (value & 0x30000) == 0x30000) {
304 if ((model & 0xF0) == 0x00) {
305 coreTemperature.Value = ((value >> 21) & 0x7FC) / 8.0f +
306 coreTemperature.Parameters[0].Value - 49;
308 coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
309 coreTemperature.Parameters[0].Value - 49;
311 } else if (family == 0x16 &&
312 ((value & 0x30000) == 0x30000 || (value & 0x80000) == 0x80000)) {
313 coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
314 coreTemperature.Parameters[0].Value - 49;
316 coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
317 coreTemperature.Parameters[0].Value;
319 ActivateSensor(coreTemperature);
321 DeactivateSensor(coreTemperature);
325 string s = ReadFirstLine(temperatureStream);
327 coreTemperature.Value = 0.001f *
328 long.Parse(s, CultureInfo.InvariantCulture);
329 ActivateSensor(coreTemperature);
331 DeactivateSensor(coreTemperature);
335 if (HasTimeStampCounter) {
336 double newBusClock = 0;
338 for (int i = 0; i < coreClocks.Length; i++) {
342 if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
343 1UL << cpuid[i][0].Thread))
346 multiplier = GetCoreMultiplier(curEax);
348 coreClocks[i].Value =
349 (float)(multiplier * TimeStampCounterFrequency /
350 timeStampCounterMultiplier);
352 (float)(TimeStampCounterFrequency / timeStampCounterMultiplier);
354 coreClocks[i].Value = (float)TimeStampCounterFrequency;
358 if (newBusClock > 0) {
359 this.busClock.Value = (float)newBusClock;
360 ActivateSensor(this.busClock);
365 public override void Close() {
366 if (temperatureStream != null) {
367 temperatureStream.Close();