Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/x86/events/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  msr.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
#include <linux/perf_event.h>
#include <linux/sysfs.h>
#include <linux/nospec.h>
#include <asm/cpu_device_id.h>
#include <asm/msr.h>

#include "probe.h"

enum perf_msr_id {
 PERF_MSR_TSC   = 0,
 PERF_MSR_APERF   = 1,
 PERF_MSR_MPERF   = 2,
 PERF_MSR_PPERF   = 3,
 PERF_MSR_SMI   = 4,
 PERF_MSR_PTSC   = 5,
 PERF_MSR_IRPERF   = 6,
 PERF_MSR_THERM   = 7,
 PERF_MSR_EVENT_MAX,
};

static bool test_aperfmperf(int idx, void *data)
{
 return boot_cpu_has(X86_FEATURE_APERFMPERF);
}

static bool test_ptsc(int idx, void *data)
{
 return boot_cpu_has(X86_FEATURE_PTSC);
}

static bool test_irperf(int idx, void *data)
{
 return boot_cpu_has(X86_FEATURE_IRPERF);
}

static bool test_therm_status(int idx, void *data)
{
 return boot_cpu_has(X86_FEATURE_DTHERM);
}

static bool test_intel(int idx, void *data)
{
 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
     boot_cpu_data.x86 != 6)
  return false;

 switch (boot_cpu_data.x86_vfm) {
 case INTEL_NEHALEM:
 case INTEL_NEHALEM_G:
 case INTEL_NEHALEM_EP:
 case INTEL_NEHALEM_EX:

 case INTEL_WESTMERE:
 case INTEL_WESTMERE_EP:
 case INTEL_WESTMERE_EX:

 case INTEL_SANDYBRIDGE:
 case INTEL_SANDYBRIDGE_X:

 case INTEL_IVYBRIDGE:
 case INTEL_IVYBRIDGE_X:

 case INTEL_HASWELL:
 case INTEL_HASWELL_X:
 case INTEL_HASWELL_L:
 case INTEL_HASWELL_G:

 case INTEL_BROADWELL:
 case INTEL_BROADWELL_D:
 case INTEL_BROADWELL_G:
 case INTEL_BROADWELL_X:
 case INTEL_SAPPHIRERAPIDS_X:
 case INTEL_EMERALDRAPIDS_X:
 case INTEL_GRANITERAPIDS_X:
 case INTEL_GRANITERAPIDS_D:

 case INTEL_ATOM_SILVERMONT:
 case INTEL_ATOM_SILVERMONT_D:
 case INTEL_ATOM_AIRMONT:

 case INTEL_ATOM_GOLDMONT:
 case INTEL_ATOM_GOLDMONT_D:
 case INTEL_ATOM_GOLDMONT_PLUS:
 case INTEL_ATOM_TREMONT_D:
 case INTEL_ATOM_TREMONT:
 case INTEL_ATOM_TREMONT_L:

 case INTEL_XEON_PHI_KNL:
 case INTEL_XEON_PHI_KNM:
  if (idx == PERF_MSR_SMI)
   return true;
  break;

 case INTEL_SKYLAKE_L:
 case INTEL_SKYLAKE:
 case INTEL_SKYLAKE_X:
 case INTEL_KABYLAKE_L:
 case INTEL_KABYLAKE:
 case INTEL_COMETLAKE_L:
 case INTEL_COMETLAKE:
 case INTEL_ICELAKE_L:
 case INTEL_ICELAKE:
 case INTEL_ICELAKE_X:
 case INTEL_ICELAKE_D:
 case INTEL_TIGERLAKE_L:
 case INTEL_TIGERLAKE:
 case INTEL_ROCKETLAKE:
 case INTEL_ALDERLAKE:
 case INTEL_ALDERLAKE_L:
 case INTEL_ATOM_GRACEMONT:
 case INTEL_RAPTORLAKE:
 case INTEL_RAPTORLAKE_P:
 case INTEL_RAPTORLAKE_S:
 case INTEL_METEORLAKE:
 case INTEL_METEORLAKE_L:
  if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
   return true;
  break;
 }

 return false;
}

PMU_EVENT_ATTR_STRING(tsc,    attr_tsc,  "event=0x00" );
PMU_EVENT_ATTR_STRING(aperf,    attr_aperf,  "event=0x01" );
PMU_EVENT_ATTR_STRING(mperf,    attr_mperf,  "event=0x02" );
PMU_EVENT_ATTR_STRING(pperf,    attr_pperf,  "event=0x03" );
PMU_EVENT_ATTR_STRING(smi,    attr_smi,  "event=0x04" );
PMU_EVENT_ATTR_STRING(ptsc,    attr_ptsc,  "event=0x05" );
PMU_EVENT_ATTR_STRING(irperf,    attr_irperf,  "event=0x06" );
PMU_EVENT_ATTR_STRING(cpu_thermal_margin,  attr_therm,  "event=0x07" );
PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot, attr_therm_snap, "1"  );
PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit,  attr_therm_unit, "C"  );

static unsigned long msr_mask;

PMU_EVENT_GROUP(events, aperf);
PMU_EVENT_GROUP(events, mperf);
PMU_EVENT_GROUP(events, pperf);
PMU_EVENT_GROUP(events, smi);
PMU_EVENT_GROUP(events, ptsc);
PMU_EVENT_GROUP(events, irperf);

static struct attribute *attrs_therm[] = {
 &attr_therm.attr.attr,
 &attr_therm_snap.attr.attr,
 &attr_therm_unit.attr.attr,
 NULL,
};

static struct attribute_group group_therm = {
 .name  = "events",
 .attrs = attrs_therm,
};

static struct perf_msr msr[] = {
 [PERF_MSR_TSC]  = { .no_check = true,        },
 [PERF_MSR_APERF] = { MSR_IA32_APERF,  &group_aperf,  test_aperfmperf, },
 [PERF_MSR_MPERF] = { MSR_IA32_MPERF,  &group_mperf,  test_aperfmperf, },
 [PERF_MSR_PPERF] = { MSR_PPERF,   &group_pperf,  test_intel,  },
 [PERF_MSR_SMI]  = { MSR_SMI_COUNT,  &group_smi,  test_intel,  },
 [PERF_MSR_PTSC]  = { MSR_F15H_PTSC,  &group_ptsc,  test_ptsc,  },
 [PERF_MSR_IRPERF] = { MSR_F17H_IRPERF,  &group_irperf,  test_irperf,  },
 [PERF_MSR_THERM] = { MSR_IA32_THERM_STATUS, &group_therm,  test_therm_status, },
};

static struct attribute *events_attrs[] = {
 &attr_tsc.attr.attr,
 NULL,
};

static struct attribute_group events_attr_group = {
 .name = "events",
 .attrs = events_attrs,
};

PMU_FORMAT_ATTR(event, "config:0-63");
static struct attribute *format_attrs[] = {
 &format_attr_event.attr,
 NULL,
};
static struct attribute_group format_attr_group = {
 .name = "format",
 .attrs = format_attrs,
};

static const struct attribute_group *attr_groups[] = {
 &events_attr_group,
 &format_attr_group,
 NULL,
};

static const struct attribute_group *attr_update[] = {
 &group_aperf,
 &group_mperf,
 &group_pperf,
 &group_smi,
 &group_ptsc,
 &group_irperf,
 &group_therm,
 NULL,
};

static int msr_event_init(struct perf_event *event)
{
 u64 cfg = event->attr.config;

 if (event->attr.type != event->pmu->type)
  return -ENOENT;

 /* unsupported modes and filters */
 if (event->attr.sample_period) /* no sampling */
  return -EINVAL;

 if (cfg >= PERF_MSR_EVENT_MAX)
  return -EINVAL;

 cfg = array_index_nospec((unsigned long)cfg, PERF_MSR_EVENT_MAX);

 if (!(msr_mask & (1 << cfg)))
  return -EINVAL;

 event->hw.idx  = -1;
 event->hw.event_base = msr[cfg].msr;
 event->hw.config = cfg;

 return 0;
}

static inline u64 msr_read_counter(struct perf_event *event)
{
 u64 now;

 if (event->hw.event_base)
  rdmsrq(event->hw.event_base, now);
 else
  now = rdtsc_ordered();

 return now;
}

static void msr_event_update(struct perf_event *event)
{
 u64 prev, now;
 s64 delta;

 /* Careful, an NMI might modify the previous event value: */
 prev = local64_read(&event->hw.prev_count);
 do {
  now = msr_read_counter(event);
 } while (!local64_try_cmpxchg(&event->hw.prev_count, &prev, now));

 delta = now - prev;
 if (unlikely(event->hw.event_base == MSR_SMI_COUNT)) {
  delta = sign_extend64(delta, 31);
  local64_add(delta, &event->count);
 } else if (unlikely(event->hw.event_base == MSR_IA32_THERM_STATUS)) {
  /* If valid, extract digital readout, otherwise 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)
{
 u64 now = msr_read_counter(event);

 local64_set(&event->hw.prev_count, now);
}

static void msr_event_stop(struct perf_event *event, int flags)
{
 msr_event_update(event);
}

static void msr_event_del(struct perf_event *event, int flags)
{
 msr_event_stop(event, PERF_EF_UPDATE);
}

static int msr_event_add(struct perf_event *event, int flags)
{
 if (flags & PERF_EF_START)
  msr_event_start(event, flags);

 return 0;
}

static struct pmu pmu_msr = {
 .task_ctx_nr = perf_sw_context,
 .attr_groups = attr_groups,
 .event_init = msr_event_init,
 .add  = msr_event_add,
 .del  = msr_event_del,
 .start  = msr_event_start,
 .stop  = msr_event_stop,
 .read  = msr_event_update,
 .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
 .attr_update = attr_update,
};

static int __init msr_init(void)
{
 if (!boot_cpu_has(X86_FEATURE_TSC)) {
  pr_cont("no MSR PMU driver.\n");
  return 0;
 }

 msr_mask = perf_msr_probe(msr, PERF_MSR_EVENT_MAX, true, NULL);

 perf_pmu_register(&pmu_msr, "msr", -1);

 return 0;
}
device_initcall(msr_init);

Messung V0.5
C=95 H=89 G=91

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.