/* Event code: LSB 8 bits, passed in attr->config any other bit is reserved. */ #define AMD_POWER_EVENT_MASK 0xFFULL
/* * Accumulated power status counters.
*/ #define AMD_POWER_EVENTSEL_PKG 1
/* * The ratio of compute unit power accumulator sample period to the * PTSC period.
*/ staticunsignedint cpu_pwr_sample_ratio;
/* Maximum accumulated power of a compute unit. */ static u64 max_cu_acc_power;
staticstruct pmu pmu_class;
/* * Accumulated power represents the sum of each compute unit's (CU) power * consumption. On any core of each CU we read the total accumulated power from * MSR_F15H_CU_PWR_ACCUMULATOR. cpu_mask represents CPU bit map of all cores * which are picked to measure the power for the CUs they belong to.
*/ static cpumask_t cpu_mask;
/* * Calculate the CU power consumption over a time period, the unit of * final value (delta) is micro-Watts. Then add it to the event count.
*/ if (new_pwr_acc < prev_pwr_acc) {
delta = max_cu_acc_power + new_pwr_acc;
delta -= prev_pwr_acc;
} else
delta = new_pwr_acc - prev_pwr_acc;
/* Mark event as deactivated and stopped. */ if (!(hwc->state & PERF_HES_STOPPED))
hwc->state |= PERF_HES_STOPPED;
/* Check if software counter update is necessary. */ if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { /* * Drain the remaining delta count out of an event * that we are disabling:
*/
event_update(event);
hwc->state |= PERF_HES_UPTODATE;
}
}
staticint power_cpu_exit(unsignedint cpu)
{ int target;
if (!cpumask_test_and_clear_cpu(cpu, &cpu_mask)) return 0;
/* * Find a new CPU on the same compute unit, if was set in cpumask * and still some CPUs on compute unit. Then migrate event and * context to new CPU.
*/
target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); if (target < nr_cpumask_bits) {
cpumask_set_cpu(target, &cpu_mask);
perf_pmu_migrate_context(&pmu_class, cpu, target);
} return 0;
}
staticint power_cpu_init(unsignedint cpu)
{ int target;
/* * 1) If any CPU is set at cpu_mask in the same compute unit, do * nothing. * 2) If no CPU is set at cpu_mask in the same compute unit, * set current ONLINE CPU. * * Note: if there is a CPU aside of the new one already in the * sibling mask, then it is also in cpu_mask.
*/
target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); if (target >= nr_cpumask_bits)
cpumask_set_cpu(cpu, &cpu_mask); return 0;
}
staticint __init amd_power_pmu_init(void)
{ int ret;
if (!x86_match_cpu(cpu_match)) return -ENODEV;
if (!boot_cpu_has(X86_FEATURE_ACC_POWER)) return -ENODEV;
cpu_pwr_sample_ratio = cpuid_ecx(0x80000007);
if (rdmsrq_safe(MSR_F15H_CU_MAX_PWR_ACCUMULATOR, &max_cu_acc_power)) {
pr_err("Failed to read max compute unit power accumulator MSR\n"); return -ENODEV;
}
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.