Exemple #1
0
            public Core(Amd17Cpu cpu, int id)
            {
                _cpu        = cpu;
                Threads     = new List <CpuId>();
                CoreId      = id;
                _clock      = new Sensor("Core #" + CoreId, cpu._sensorClock++, SensorType.Clock, cpu, cpu._settings);
                _multiplier = new Sensor("Core #" + CoreId, cpu._sensorMulti++, SensorType.Factor, cpu, cpu._settings);
                _power      = new Sensor("Core #" + CoreId + " (SMU)", cpu._sensorPower++, SensorType.Power, cpu, cpu._settings);
                _vcore      = new Sensor("Core #" + CoreId + " VID", cpu._sensorVoltage++, SensorType.Voltage, cpu, cpu._settings);

                cpu.ActivateSensor(_clock);
                cpu.ActivateSensor(_multiplier);
                cpu.ActivateSensor(_power);
                cpu.ActivateSensor(_vcore);
            }
            public Processor(Hardware hw)
            {
                _hw   = (Amd17Cpu)hw;
                Nodes = new List <NumaNode>();

                _packagePower        = new Sensor("Package Power", _hw._sensorPower++, SensorType.Power, _hw, _hw._settings);
                _coreTemperatureTctl = new Sensor("Core (Tctl)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
                _coreTemperatureTdie = new Sensor("Core (Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
                _coreVoltage         = new Sensor("Core (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
                _socVoltage          = new Sensor("SoC (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);

                _hw.ActivateSensor(_packagePower);
                _hw.ActivateSensor(_coreTemperatureTctl);
                _hw.ActivateSensor(_coreTemperatureTdie);
                _hw.ActivateSensor(_coreVoltage);
            }
Exemple #3
0
            public Processor(Hardware hardware)
            {
                _cpu = (Amd17Cpu)hardware;

                _packagePower            = new Sensor("Package Power", _cpu._sensorPower++, SensorType.Power, _cpu, _cpu._settings);
                _coreTemperatureTctl     = new Sensor("Core (Tctl)", _cpu._sensorTemperatures++, SensorType.Temperature, _cpu, _cpu._settings);
                _coreTemperatureTdie     = new Sensor("Core (Tdie)", _cpu._sensorTemperatures++, SensorType.Temperature, _cpu, _cpu._settings);
                _coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _cpu._sensorTemperatures++, SensorType.Temperature, _cpu, _cpu._settings);
                _ccdTemperatures         = new Sensor[8]; // Hardcoded until there's a way to get max CCDs.
                _coreVoltage             = new Sensor("Core (SVI2 TFN)", _cpu._sensorVoltage++, SensorType.Voltage, _cpu, _cpu._settings);
                _socVoltage = new Sensor("SoC (SVI2 TFN)", _cpu._sensorVoltage++, SensorType.Voltage, _cpu, _cpu._settings);
                _busClock   = new Sensor("Bus Speed", _cpu._sensorClock++, SensorType.Clock, _cpu, _cpu._settings);

                _cpu.ActivateSensor(_packagePower);
            }
Exemple #4
0
            public Processor(Hardware hw)
            {
                _hw   = (Amd17Cpu)hw;
                Nodes = new List <NumaNode>();

                _packagePower            = new Sensor("Package Power", _hw._sensorPower++, SensorType.Power, _hw, _hw._settings);
                _coreTemperatureTctl     = new Sensor("Core (Tctl)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
                _coreTemperatureTdie     = new Sensor("Core (Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
                _coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
                _ccdTemperatures         = new Sensor[8]; // Hardcoded until there's a way to get max CCDs.
                _coreVoltage             = new Sensor("Core (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
                _socVoltage = new Sensor("SoC (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);

                _hw.ActivateSensor(_packagePower);
            }
Exemple #5
0
            public void UpdateSensors()
            {
                NumaNode node  = Nodes[0];
                Core     core  = node?.Cores[0];
                CpuId    cpuId = core?.Threads[0];

                if (cpuId == null)
                {
                    return;
                }


                GroupAffinity previousAffinity = ThreadAffinity.Set(cpuId.Affinity);

                // MSRC001_0299
                // TU [19:16]
                // ESU [12:8] -> Unit 15.3 micro Joule per increment
                // PU [3:0]
                Ring0.ReadMsr(MSR_PWR_UNIT, out uint _, out uint _);

                // MSRC001_029B
                // total_energy [31:0]
                DateTime sampleTime = DateTime.Now;

                Ring0.ReadMsr(MSR_PKG_ENERGY_STAT, out uint eax, out _);

                uint totalEnergy = eax;

                uint smuSvi0Tfn       = 0;
                uint smuSvi0TelPlane0 = 0;
                uint smuSvi0TelPlane1 = 0;

                if (Ring0.WaitPciBusMutex(10))
                {
                    // THM_TCON_CUR_TMP
                    // CUR_TEMP [31:21]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature);

                    // SVI0_TFN_PLANE0 [0]
                    // SVI0_TFN_PLANE1 [1]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0Tfn);

                    bool supportsPerCcdTemperatures = false;

                    // TODO: find a better way because these will probably keep changing in the future.

                    uint sviPlane0Offset;
                    uint sviPlane1Offset;
                    switch (cpuId.Model)
                    {
                    case 0x31:     // Threadripper 3000.
                    {
                        sviPlane0Offset            = F17H_M01H_SVI + 0x14;
                        sviPlane1Offset            = F17H_M01H_SVI + 0x10;
                        supportsPerCcdTemperatures = true;
                        break;
                    }

                    case 0x71:     // Zen 2.
                    case 0x21:     // Zen 3.
                    {
                        sviPlane0Offset            = F17H_M01H_SVI + 0x10;
                        sviPlane1Offset            = F17H_M01H_SVI + 0xC;
                        supportsPerCcdTemperatures = true;
                        break;
                    }

                    default:     // Zen and Zen+.
                    {
                        sviPlane0Offset = F17H_M01H_SVI + 0xC;
                        sviPlane1Offset = F17H_M01H_SVI + 0x10;
                        break;
                    }
                    }

                    // SVI0_PLANE0_VDDCOR [24:16]
                    // SVI0_PLANE0_IDDCOR [7:0]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane0Offset);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0TelPlane0);

                    // SVI0_PLANE1_VDDCOR [24:16]
                    // SVI0_PLANE1_IDDCOR [7:0]
                    Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset);
                    Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out smuSvi0TelPlane1);

                    ThreadAffinity.Set(previousAffinity);

                    // power consumption
                    // power.Value = (float) ((double)pu * 0.125);
                    // esu = 15.3 micro Joule per increment
                    if (_lastPwrTime.Ticks == 0)
                    {
                        _lastPwrTime  = sampleTime;
                        _lastPwrValue = totalEnergy;
                    }

                    // ticks diff
                    TimeSpan time = sampleTime - _lastPwrTime;
                    long     pwr;
                    if (_lastPwrValue <= totalEnergy)
                    {
                        pwr = totalEnergy - _lastPwrValue;
                    }
                    else
                    {
                        pwr = (0xffffffff - _lastPwrValue) + totalEnergy;
                    }

                    // update for next sample
                    _lastPwrTime  = sampleTime;
                    _lastPwrValue = totalEnergy;

                    double energy = 15.3e-6 * pwr;
                    energy /= time.TotalSeconds;

                    if (!double.IsNaN(energy))
                    {
                        _packagePower.Value = (float)energy;
                    }

                    // current temp Bit [31:21]
                    // If bit 19 of the Temperature Control register is set, there is an additional offset of 49 degrees C.
                    bool tempOffsetFlag = (temperature & F17H_TEMP_OFFSET_FLAG) != 0;
                    temperature = (temperature >> 21) * 125;

                    float offset = 0.0f;

                    // Offset table: https://github.com/torvalds/linux/blob/master/drivers/hwmon/k10temp.c#L78
                    if (string.IsNullOrWhiteSpace(cpuId.Name))
                    {
                        offset = 0;
                    }
                    else if (cpuId.Name.Contains("1600X") || cpuId.Name.Contains("1700X") || cpuId.Name.Contains("1800X"))
                    {
                        offset = -20.0f;
                    }
                    else if (cpuId.Name.Contains("Threadripper 19") || cpuId.Name.Contains("Threadripper 29"))
                    {
                        offset = -27.0f;
                    }
                    else if (cpuId.Name.Contains("2700X"))
                    {
                        offset = -10.0f;
                    }

                    float t = temperature * 0.001f;
                    if (tempOffsetFlag)
                    {
                        t += -49.0f;
                    }

                    if (offset < 0)
                    {
                        _coreTemperatureTctl.Value = t;
                        _coreTemperatureTdie.Value = t + offset;

                        _cpu.ActivateSensor(_coreTemperatureTctl);
                        _cpu.ActivateSensor(_coreTemperatureTdie);
                    }
                    else
                    {
                        // Zen 2 doesn't have an offset so Tdie and Tctl are the same.
                        _coreTemperatureTctlTdie.Value = t;
                        _cpu.ActivateSensor(_coreTemperatureTctlTdie);
                    }

                    // Tested only on R5 3600 & Threadripper 3960X.
                    if (supportsPerCcdTemperatures)
                    {
                        for (uint i = 0; i < _ccdTemperatures.Length; i++)
                        {
                            Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M70H_CCD1_TEMP + (i * 0x4));
                            Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint ccdRawTemp);

                            ccdRawTemp &= 0xFFF;
                            float ccdTemp = ((ccdRawTemp * 125) - 305000) * 0.001f;
                            if (ccdRawTemp > 0 && ccdTemp < 125)  // Zen 2 reports 95 degrees C max, but it might exceed that.
                            {
                                if (_ccdTemperatures[i] == null)
                                {
                                    _cpu.ActivateSensor(_ccdTemperatures[i] = new Sensor($"CCD{i + 1} (Tdie)",
                                                                                         _cpu._sensorTemperatures++,
                                                                                         SensorType.Temperature,
                                                                                         _cpu,
                                                                                         _cpu._settings));
                                }
                                _ccdTemperatures[i].Value = ccdTemp;
                            }
                        }

                        Sensor[] activeCcds = _ccdTemperatures.Where(x => x != null).ToArray();
                        if (activeCcds.Length > 1)
                        {
                            // No need to get the max / average ccds temp if there is only one CCD.

                            if (_ccdsMaxTemperature == null)
                            {
                                _cpu.ActivateSensor(_ccdsMaxTemperature = new Sensor("CCDs Max (Tdie)",
                                                                                     _cpu._sensorTemperatures++,
                                                                                     SensorType.Temperature,
                                                                                     _cpu,
                                                                                     _cpu._settings));
                            }

                            if (_ccdsAverageTemperature == null)
                            {
                                _cpu.ActivateSensor(_ccdsAverageTemperature = new Sensor("CCDs Average (Tdie)",
                                                                                         _cpu._sensorTemperatures++,
                                                                                         SensorType.Temperature,
                                                                                         _cpu,
                                                                                         _cpu._settings));
                            }

                            _ccdsMaxTemperature.Value     = activeCcds.Max(x => x.Value);
                            _ccdsAverageTemperature.Value = activeCcds.Average(x => x.Value);
                        }
                    }
                    Ring0.ReleasePciBusMutex();
                }

                // voltage
                const double vidStep = 0.00625;
                double       vcc;
                uint         svi0PlaneXVddCor;

                // Core (0x01).
                if ((smuSvi0Tfn & 0x01) == 0)
                {
                    svi0PlaneXVddCor = (smuSvi0TelPlane0 >> 16) & 0xff;
                    vcc = 1.550 - vidStep * svi0PlaneXVddCor;
                    _coreVoltage.Value = (float)vcc;

                    _cpu.ActivateSensor(_coreVoltage);
                }

                // SoC (0x02), not every Zen cpu has this voltage.
                if (cpuId.Model == 0x21 || cpuId.Model == 0x71 || cpuId.Model == 0x31 || (smuSvi0Tfn & 0x02) == 0)
                {
                    svi0PlaneXVddCor = (smuSvi0TelPlane1 >> 16) & 0xff;
                    vcc = 1.550 - vidStep * svi0PlaneXVddCor;
                    _socVoltage.Value = (float)vcc;

                    _cpu.ActivateSensor(_socVoltage);
                }

                double timeStampCounterMultiplier = GetTimeStampCounterMultiplier();

                if (timeStampCounterMultiplier > 0)
                {
                    _busClock.Value = (float)(_cpu.TimeStampCounterFrequency / timeStampCounterMultiplier);
                    _cpu.ActivateSensor(_busClock);
                }
            }
            public void UpdateSensors()
            {
                var   node = Nodes[0];
                Core  core = node?.Cores[0];
                CpuId cpu  = core?.Threads[0];

                if (cpu == null)
                {
                    return;
                }


                ulong mask = Ring0.ThreadAffinitySet(1UL << cpu.Thread);

                // MSRC001_0299
                // TU [19:16]
                // ESU [12:8] -> Unit 15.3 micro Joule per increment
                // PU [3:0]
                Ring0.ReadMsr(MSR_PWR_UNIT, out uint _, out uint _);

                // MSRC001_029B
                // total_energy [31:0]
                DateTime sampleTime = DateTime.Now;

                Ring0.ReadMsr(MSR_PKG_ENERGY_STAT, out uint eax, out _);
                uint totalEnergy = eax;

                // THM_TCON_CUR_TMP
                // CUR_TEMP [31:21]
                Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
                Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature);

                // SVI0_TFN_PLANE0 [0]
                // SVI0_TFN_PLANE1 [1]
                Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8);
                Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0Tfn);

                // SVI0_PLANE0_VDDCOR [24:16]
                // SVI0_PLANE0_IDDCOR [7:0]
                Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0xc);
                Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane0);

                // SVI0_PLANE1_VDDCOR [24:16]
                // SVI0_PLANE1_IDDCOR [7:0]
                Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x10);
                Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1);

                Ring0.ThreadAffinitySet(mask);

                // power consumption
                // power.Value = (float) ((double)pu * 0.125);
                // esu = 15.3 micro Joule per increment
                if (_lastPwrTime.Ticks == 0)
                {
                    _lastPwrTime  = sampleTime;
                    _lastPwrValue = totalEnergy;
                }

                // ticks diff
                TimeSpan time = sampleTime - _lastPwrTime;
                long     pwr;

                if (_lastPwrValue <= totalEnergy)
                {
                    pwr = totalEnergy - _lastPwrValue;
                }
                else
                {
                    pwr = (0xffffffff - _lastPwrValue) + totalEnergy;
                }

                // update for next sample
                _lastPwrTime  = sampleTime;
                _lastPwrValue = totalEnergy;

                double energy = 15.3e-6 * pwr;

                energy /= time.TotalSeconds;

                if (!double.IsNaN(energy))
                {
                    _packagePower.Value = (float)energy;
                }

                // current temp Bit [31:21]
                //If bit 19 of the Temperature Control register is set, there is an additional offset of 49 degrees C.
                bool tempOffsetFlag = (temperature & F17H_TEMP_OFFSET_FLAG) != 0;

                temperature = (temperature >> 21) * 125;

                float offset = 0.0f;

                if (string.IsNullOrWhiteSpace(cpu.Name))
                {
                    offset = 0;
                }
                else if (cpu.Name.Contains("1600X") || cpu.Name.Contains("1700X") || cpu.Name.Contains("1800X"))
                {
                    offset = -20.0f;
                }
                else if (cpu.Name.Contains("1920X") ||
                         cpu.Name.Contains("1950X") ||
                         cpu.Name.Contains("1900X") ||
                         cpu.Name.Contains("2920") ||
                         cpu.Name.Contains("2950") ||
                         cpu.Name.Contains("2970") ||
                         cpu.Name.Contains("2990"))
                {
                    offset = -27.0f;
                }
                else if (cpu.Name.Contains("2600X") ||
                         cpu.Name.Contains("2700X") ||
                         cpu.Name.Contains("2800X") ||
                         cpu.Name.Contains("1910") ||
                         cpu.Name.Contains("1920") ||
                         cpu.Name.Contains("1950"))
                {
                    offset = -10.0f;
                }

                float t = temperature * 0.001f;

                if (tempOffsetFlag)
                {
                    t += -49.0f;
                }

                _coreTemperatureTctl.Value = t;
                _coreTemperatureTdie.Value = t + offset;

                // voltage
                double vidStep = 0.00625;
                double vcc;
                uint   svi0PlaneXVddCor;

                //Core
                if ((smuSvi0Tfn & 0x01) == 0)
                {
                    svi0PlaneXVddCor = (smuSvi0TelPlane0 >> 16) & 0xff;
                    vcc = 1.550 - vidStep * svi0PlaneXVddCor;
                    _coreVoltage.Value = (float)vcc;
                }

                // SoC
                // not every zen cpu has this voltage
                if ((smuSvi0Tfn & 0x02) == 0)
                {
                    svi0PlaneXVddCor = (smuSvi0TelPlane1 >> 16) & 0xff;
                    vcc = 1.550 - vidStep * svi0PlaneXVddCor;
                    _socVoltage.Value = (float)vcc;
                    _hw.ActivateSensor(_socVoltage);
                }
            }