mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-31 22:35:11 +00:00
A first (experimental) implementation for the AMD 10h family CPU clock speeds.
This commit is contained in:
@@ -107,7 +107,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
StringBuilder r = new StringBuilder();
|
StringBuilder r = new StringBuilder();
|
||||||
r.Append(base.GetReport());
|
r.Append(base.GetReport());
|
||||||
|
|
||||||
r.Append("Miscellaneous Control Address: ");
|
r.Append("Miscellaneous Control Address: 0x");
|
||||||
r.AppendLine((miscellaneousControlAddress).ToString("X",
|
r.AppendLine((miscellaneousControlAddress).ToString("X",
|
||||||
CultureInfo.InvariantCulture));
|
CultureInfo.InvariantCulture));
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
@@ -38,16 +38,22 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace OpenHardwareMonitor.Hardware.CPU {
|
namespace OpenHardwareMonitor.Hardware.CPU {
|
||||||
|
|
||||||
internal sealed class AMD10CPU : AMDCPU {
|
internal sealed class AMD10CPU : AMDCPU {
|
||||||
|
|
||||||
private readonly Sensor coreTemperature;
|
private readonly Sensor coreTemperature;
|
||||||
|
private readonly Sensor[] coreClocks;
|
||||||
|
private readonly Sensor busClock;
|
||||||
|
|
||||||
|
private const uint COFVID_STATUS = 0xC0010071;
|
||||||
|
private const uint P_STATE_0 = 0xC0010064;
|
||||||
|
|
||||||
private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
|
private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
|
||||||
private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
|
private const ushort MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
|
||||||
private const byte REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
|
private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
|
||||||
|
|
||||||
private readonly uint miscellaneousControlAddress;
|
private readonly uint miscellaneousControlAddress;
|
||||||
|
|
||||||
@@ -65,18 +71,27 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
miscellaneousControlAddress = GetPciAddress(
|
miscellaneousControlAddress = GetPciAddress(
|
||||||
MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
|
MISCELLANEOUS_CONTROL_FUNCTION, MISCELLANEOUS_CONTROL_DEVICE_ID);
|
||||||
|
|
||||||
|
busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
|
||||||
|
coreClocks = new Sensor[coreCount];
|
||||||
|
for (int i = 0; i < coreClocks.Length; i++) {
|
||||||
|
coreClocks[i] = new Sensor(CoreString(i), i + 1, SensorType.Clock,
|
||||||
|
this, settings);
|
||||||
|
if (hasTSC)
|
||||||
|
ActivateSensor(coreClocks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override uint[] GetMSRs() {
|
protected override uint[] GetMSRs() {
|
||||||
return new uint[] { };
|
return new uint[] { P_STATE_0, COFVID_STATUS };
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetReport() {
|
public override string GetReport() {
|
||||||
StringBuilder r = new StringBuilder();
|
StringBuilder r = new StringBuilder();
|
||||||
r.Append(base.GetReport());
|
r.Append(base.GetReport());
|
||||||
|
|
||||||
r.Append("Miscellaneous Control Address: ");
|
r.Append("Miscellaneous Control Address: 0x");
|
||||||
r.AppendLine((miscellaneousControlAddress).ToString("X",
|
r.AppendLine((miscellaneousControlAddress).ToString("X",
|
||||||
CultureInfo.InvariantCulture));
|
CultureInfo.InvariantCulture));
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
@@ -84,6 +99,10 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
return r.ToString();
|
return r.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double MultiplierFromIDs(uint divisorID, uint frequencyID) {
|
||||||
|
return 0.5 * (frequencyID + 0x10) / (1 << (int)divisorID);
|
||||||
|
}
|
||||||
|
|
||||||
public override void Update() {
|
public override void Update() {
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
@@ -98,6 +117,44 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
DeactivateSensor(coreTemperature);
|
DeactivateSensor(coreTemperature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (hasTSC) {
|
||||||
|
double newBusClock = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < coreClocks.Length; i++) {
|
||||||
|
Thread.Sleep(1);
|
||||||
|
|
||||||
|
uint curEax, curEdx;
|
||||||
|
uint maxEax, maxEdx;
|
||||||
|
if (WinRing0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
|
||||||
|
(UIntPtr)(1L << cpuid[i][0].Thread)) &&
|
||||||
|
WinRing0.RdmsrTx(P_STATE_0, out maxEax, out maxEdx,
|
||||||
|
(UIntPtr)(1L << cpuid[i][0].Thread)))
|
||||||
|
{
|
||||||
|
// 8:6 CpuDid: current core divisor ID
|
||||||
|
// 5:0 CpuFid: current core frequency ID
|
||||||
|
uint curCpuDid = (curEax >> 6) & 7;
|
||||||
|
uint curCpuFid = curEax & 0x1F;
|
||||||
|
double multiplier = MultiplierFromIDs(curCpuDid, curCpuFid);
|
||||||
|
|
||||||
|
// we assume that the max multiplier (used for the TSC)
|
||||||
|
// can be found in the P_STATE_0 MSR
|
||||||
|
uint maxCpuDid = (maxEax >> 6) & 7;
|
||||||
|
uint maxCpuFid = maxEax & 0x1F;
|
||||||
|
double maxMultiplier = MultiplierFromIDs(maxCpuDid, maxCpuFid);
|
||||||
|
|
||||||
|
coreClocks[i].Value = (float)(multiplier * MaxClock / maxMultiplier);
|
||||||
|
newBusClock = (float)(MaxClock / maxMultiplier);
|
||||||
|
} else {
|
||||||
|
coreClocks[i].Value = (float)MaxClock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newBusClock > 0) {
|
||||||
|
this.busClock.Value = (float)newBusClock;
|
||||||
|
ActivateSensor(this.busClock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,14 +48,17 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
: base(processorIndex, cpuid, settings) { }
|
: base(processorIndex, cpuid, settings) { }
|
||||||
|
|
||||||
protected uint GetPciAddress(byte function, ushort deviceId) {
|
protected uint GetPciAddress(byte function, ushort deviceId) {
|
||||||
|
|
||||||
|
// assemble the pci address
|
||||||
uint address = WinRing0.GetPciAddress(PCI_BUS,
|
uint address = WinRing0.GetPciAddress(PCI_BUS,
|
||||||
(byte)(PCI_BASE_DEVICE + processorIndex), function);
|
(byte)(PCI_BASE_DEVICE + processorIndex), function);
|
||||||
|
|
||||||
|
// verify that we have the correct bus, device and function
|
||||||
uint deviceVendor;
|
uint deviceVendor;
|
||||||
if (!WinRing0.ReadPciConfigDwordEx(
|
if (!WinRing0.ReadPciConfigDwordEx(
|
||||||
address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
|
address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
|
||||||
return WinRing0.InvalidPciAddress;
|
return WinRing0.InvalidPciAddress;
|
||||||
|
|
||||||
if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
|
if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
|
||||||
return WinRing0.InvalidPciAddress;
|
return WinRing0.InvalidPciAddress;
|
||||||
|
|
||||||
|
@@ -37,5 +37,5 @@
|
|||||||
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("0.1.37.14")]
|
[assembly: AssemblyVersion("0.1.37.16")]
|
||||||
[assembly: AssemblyInformationalVersion("0.1.37.14 Alpha")]
|
[assembly: AssemblyInformationalVersion("0.1.37.16 Alpha")]
|
Reference in New Issue
Block a user