/* set maximum interval as 1 second */ #define MAX_INTERVAL 1000
#define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4
struct fam15h_power_data { struct pci_dev *pdev; unsignedint tdp_to_watts; unsignedint base_tdp; unsignedint processor_pwr_watts; unsignedint cpu_pwr_sample_ratio; conststruct attribute_group *groups[FAM15H_NUM_GROUPS]; struct attribute_group group; /* maximum accumulated power of a compute unit */
u64 max_cu_acc_power; /* accumulated power of the compute units */
u64 cu_acc_power[MAX_CUS]; /* performance timestamp counter */
u64 cpu_sw_pwr_ptsc[MAX_CUS]; /* online/offline status of current compute unit */ int cu_on[MAX_CUS]; unsignedlong power_period;
};
/* * On Carrizo and later platforms, TdpRunAvgAccCap bit field * is extended to 4:31 from 4:25.
*/ if (is_carrizo_or_later()) {
running_avg_capture = val >> 4;
running_avg_capture = sign_extend32(running_avg_capture, 27);
} else {
running_avg_capture = (val >> 4) & 0x3fffff;
running_avg_capture = sign_extend32(running_avg_capture, 21);
}
/* * On Carrizo and later platforms, ApmTdpLimit bit field * is extended to 16:31 from 16:28.
*/ if (is_carrizo_or_later())
tdp_limit = val >> 16; else
tdp_limit = (val >> 16) & 0x1fff;
/* * Convert to microWatt * * power is in Watt provided as fixed point integer with * scaling factor 1/(2^16). For conversion we use * (10^6)/(2^16) = 15625/(2^10)
*/
curr_pwr_watts = (curr_pwr_watts * 15625) >> (10 + running_avg_range); return sprintf(buf, "%u\n", (unsignedint) curr_pwr_watts);
} static DEVICE_ATTR_RO(power1_input);
/* * This function is only able to be called when CPUID * Fn8000_0007:EDX[12] is set.
*/ staticint read_registers(struct fam15h_power_data *data)
{ int core, this_core;
cpumask_var_t mask; int ret, cpu;
ret = zalloc_cpumask_var(&mask, GFP_KERNEL); if (!ret) return -ENOMEM;
memset(data->cu_on, 0, sizeof(int) * MAX_CUS);
cpus_read_lock();
/* * Choose the first online core of each compute unit, and then * read their MSR value of power and ptsc in a single IPI, * because the MSR value of CPU core represent the compute * unit's.
*/
core = -1;
/* * Newer BKDG versions have an updated recommendation on how to properly * initialize the running average range (was: 0xE, now: 0x9). This avoids * counter saturations resulting in bogus power readings. * We correct this value ourselves to cope with older BIOSes.
*/ staticconststruct pci_device_id affected_device[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
{ 0 }
};
/* * let this quirk apply only to the current version of the * northbridge, since future versions may change the behavior
*/ if (!pci_match_id(affected_device, pdev)) return;
/* result not allowed to be >= 256W */ if ((tmp >> 16) >= 256)
dev_warn(&f4->dev, "Bogus value for ProcessorPwrWatts (processor_pwr_watts>=%u)\n",
(unsignedint) (tmp >> 16));
ret = fam15h_power_init_attrs(f4, data); if (ret) return ret;
/* CPUID Fn8000_0007:EDX[12] indicates to support accumulated power */ if (!boot_cpu_has(X86_FEATURE_ACC_POWER)) return 0;
/* * determine the ratio of the compute unit power accumulator * sample period to the PTSC counter period by executing CPUID * Fn8000_0007:ECX
*/
data->cpu_pwr_sample_ratio = cpuid_ecx(0x80000007);
if (rdmsrq_safe(MSR_F15H_CU_MAX_PWR_ACCUMULATOR, &tmp)) {
pr_err("Failed to read max compute unit power accumulator MSR\n"); return -ENODEV;
}
data->max_cu_acc_power = tmp;
/* * Milliseconds are a reasonable interval for the measurement. * But it shouldn't set too long here, because several seconds * would cause the read function to hang. So set default * interval as 10 ms.
*/
data->power_period = 10;
/* * though we ignore every other northbridge, we still have to * do the tweaking on _each_ node in MCM processors as the counters * are working hand-in-hand
*/
tweak_runavg_range(pdev);
if (!should_load_on_this_node(pdev)) return -ENODEV;
data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL); if (!data) return -ENOMEM;
ret = fam15h_power_init_data(pdev, data); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.