|
@@ -10,7 +10,9 @@ enum perf_msr_id {
|
|
|
PERF_MSR_SMI = 4,
|
|
|
PERF_MSR_PTSC = 5,
|
|
|
PERF_MSR_IRPERF = 6,
|
|
|
-
|
|
|
+ PERF_MSR_THERM = 7,
|
|
|
+ PERF_MSR_THERM_SNAP = 8,
|
|
|
+ PERF_MSR_THERM_UNIT = 9,
|
|
|
PERF_MSR_EVENT_MAX,
|
|
|
};
|
|
|
|
|
@@ -29,6 +31,12 @@ static bool test_irperf(int idx)
|
|
|
return boot_cpu_has(X86_FEATURE_IRPERF);
|
|
|
}
|
|
|
|
|
|
+static bool test_therm_status(int idx)
|
|
|
+{
|
|
|
+ return boot_cpu_has(X86_FEATURE_DTHERM);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static bool test_intel(int idx)
|
|
|
{
|
|
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
|
|
@@ -102,6 +110,9 @@ PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
|
|
|
PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04");
|
|
|
PMU_EVENT_ATTR_STRING(ptsc, evattr_ptsc, "event=0x05");
|
|
|
PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
|
|
|
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin, evattr_therm, "event=0x07");
|
|
|
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot, evattr_therm_snap, "1");
|
|
|
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit, evattr_therm_unit, "C");
|
|
|
|
|
|
static struct perf_msr msr[] = {
|
|
|
[PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, },
|
|
@@ -111,6 +122,9 @@ static struct perf_msr msr[] = {
|
|
|
[PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, },
|
|
|
[PERF_MSR_PTSC] = { MSR_F15H_PTSC, &evattr_ptsc, test_ptsc, },
|
|
|
[PERF_MSR_IRPERF] = { MSR_F17H_IRPERF, &evattr_irperf, test_irperf, },
|
|
|
+ [PERF_MSR_THERM] = { MSR_IA32_THERM_STATUS, &evattr_therm, test_therm_status, },
|
|
|
+ [PERF_MSR_THERM_SNAP] = { MSR_IA32_THERM_STATUS, &evattr_therm_snap, test_therm_status, },
|
|
|
+ [PERF_MSR_THERM_UNIT] = { MSR_IA32_THERM_STATUS, &evattr_therm_unit, test_therm_status, },
|
|
|
};
|
|
|
|
|
|
static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
|
|
@@ -193,10 +207,15 @@ again:
|
|
|
goto again;
|
|
|
|
|
|
delta = now - prev;
|
|
|
- if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
|
|
|
+ if (unlikely(event->hw.event_base == MSR_SMI_COUNT)) {
|
|
|
delta = sign_extend64(delta, 31);
|
|
|
-
|
|
|
- local64_add(delta, &event->count);
|
|
|
+ local64_add(delta, &event->count);
|
|
|
+ } else if (unlikely(event->hw.event_base == MSR_IA32_THERM_STATUS)) {
|
|
|
+ /* if valid, extract digital readout, other set to -1 */
|
|
|
+ now = now & (1ULL << 31) ? (now >> 16) & 0x3f : -1;
|
|
|
+ local64_set(&event->count, now);
|
|
|
+ } else
|
|
|
+ local64_add(delta, &event->count);
|
|
|
}
|
|
|
|
|
|
static void msr_event_start(struct perf_event *event, int flags)
|