-/*
- * Identify the functionality of the CPU
- */
-static int __attribute__((warn_unused_result))
-probe_cpu()
-{
- unsigned int eax, ebx, ecx, edx, max_level;
- unsigned int fms, family, model;
-
- /* CPUID(0):
- * - EAX: Maximum Input Value for Basic CPUID Information
- * - EBX: "Genu" (0x756e6547)
- * - EDX: "ineI" (0x49656e69)
- * - ECX: "ntel" (0x6c65746e)
- */
- max_level = ebx = ecx = edx = 0;
- __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
- if (ebx != 0x756e6547 && edx != 0x49656e69 && ecx != 0x6c65746e) {
- ERROR("Unsupported CPU");
- return -UNSUPPORTED_CPU;
- }
-
- /* CPUID(1):
- * - EAX: Version Information: Type, Family, Model, and Stepping ID
- * + 4-7: Model ID
- * + 8-11: Family ID
- * + 12-13: Processor type
- * + 16-19: Extended Model ID
- * + 20-27: Extended Family ID
- * - EDX: Feature Information:
- * + 5: Support for MSR read/write operations
- */
- fms = ebx = ecx = edx = 0;
- __get_cpuid(1, &fms, &ebx, &ecx, &edx);
- family = (fms >> 8) & 0xf;
- model = (fms >> 4) & 0xf;
- if (family == 0xf)
- family += (fms >> 20) & 0xf;
- if (family == 6 || family == 0xf)
- model += ((fms >> 16) & 0xf) << 4;
- if (!(edx & (1 << 5))) {
- ERROR("CPUID: no MSR");
- return -ERR_NO_MSR;
- }
-
- /*
- * CPUID(0x80000000):
- * - EAX: Maximum Input Value for Extended Function CPUID Information
- *
- * This allows us to verify if the CPUID(0x80000007) can be called
- *
- * This check is valid for both Intel and AMD.
- */
- max_level = ebx = ecx = edx = 0;
- __get_cpuid(0x80000000, &max_level, &ebx, &ecx, &edx);
- if (max_level < 0x80000007) {
- ERROR("CPUID: no invariant TSC (max_level 0x%x)", max_level);
- return -ERR_NO_INVARIANT_TSC;
- }
-
- /*
- * CPUID(0x80000007):
- * - EDX:
- * + 8: Invariant TSC available if set
- *
- * This check is valid for both Intel and AMD
- */
- eax = ebx = ecx = edx = 0;
- __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
- if (!(edx & (1 << 8))) {
- ERROR("No invariant TSC");
- return -ERR_NO_INVARIANT_TSC;
- }
-
- /*
- * CPUID(6):
- * - EAX:
- * + 0: Digital temperature sensor is supported if set
- * + 6: Package thermal management is supported if set
- * - ECX:
- * + 0: Hardware Coordination Feedback Capability (Presence of IA32_MPERF and IA32_APERF).
- * + 3: The processor supports performance-energy bias preference if set.
- * It also implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS
- *
- * This check is valid for both Intel and AMD
- */
- eax = ebx = ecx = edx = 0;
- __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
- do_dts = eax & (1 << 0);
- do_ptm = eax & (1 << 6);
- if (!(ecx & (1 << 0))) {
- ERROR("No APERF");
- return -ERR_NO_APERF;
- }
-
- /*
- * Enable or disable C states depending on the model and family
- */
- if (family == 6) {
- switch (model) {
- /* Atom (partial) */
- case 0x27:
- do_core_cstate = 0;
- do_pkg_cstate = (1 << 2) | (1 << 4) | (1 << 6);
- break;
- /* Silvermont */
- case 0x37: /* BYT */
- case 0x4A:
- case 0x4D: /* AVN */
- case 0x5A:
- case 0x5D:
- do_core_cstate = (1 << 1) | (1 << 6);
- do_pkg_cstate = (1 << 6);
- break;
- /* Nehalem */
- case 0x1A: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
- case 0x1E: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
- case 0x1F: /* Core i7 and i5 Processor - Nehalem */
- case 0x2E: /* Nehalem-EX Xeon - Beckton */
- do_core_cstate = (1 << 3) | (1 << 6);
- do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- break;
- /* Westmere */
- case 0x25: /* Westmere Client - Clarkdale, Arrandale */
- case 0x2C: /* Westmere EP - Gulftown */
- case 0x2F: /* Westmere-EX Xeon - Eagleton */
- do_core_cstate = (1 << 3) | (1 << 6);
- do_pkg_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- break;
- /* Sandy Bridge */
- case 0x2A: /* SNB */
- case 0x2D: /* SNB Xeon */
- do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
- break;
- /* Ivy Bridge */
- case 0x3A: /* IVB */
- case 0x3E: /* IVB Xeon */
- do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
- break;
- /* Haswell Bridge */
- case 0x3C: /* HSW */
- case 0x3F: /* HSW */
- case 0x46: /* HSW */
- do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
- break;
- case 0x45: /* HSW */
- do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10);
- break;
- /* Broadwel */
- case 0x4F: /* BDW */
- case 0x56: /* BDX-DE */
- do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7);
- break;
- case 0x3D: /* BDW */
- do_core_cstate = (1 << 3) | (1 << 6) | (1 << 7);
- do_pkg_cstate = (1 << 2) | (1 << 3) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10);
- break;
- default:
- ERROR("Unsupported CPU");
- }
- switch (model) {
- case 0x2A:
- case 0x3A:
- case 0x3C:
- case 0x45:
- case 0x46:
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_PKG_POWER_INFO | RAPL_GFX;
- break;
- case 0x3F:
- do_rapl = RAPL_PKG | RAPL_PKG_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM | RAPL_DRAM_PERF_STATUS;
- break;
- case 0x2D:
- case 0x3E:
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_PKG_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM | RAPL_DRAM_PERF_STATUS;
- break;
- case 0x37:
- case 0x4D:
- do_rapl = RAPL_PKG | RAPL_CORES;
- break;
- default:
- do_rapl = 0;
- }
- } else {
- ERROR("Unsupported CPU");
- return -UNSUPPORTED_CPU;
- }
-
- if (do_rapl) {
- unsigned long long msr;
- if (get_msr(0, MSR_RAPL_POWER_UNIT, &msr))
- return 0;
-
- if (model == 0x37)
- rapl_energy_units = 1.0 * (1 << (msr >> 8 & 0x1F)) / 1000000;
- else
- rapl_energy_units = 1.0 / (1 << (msr >> 8 & 0x1F));
- }
-
- return 0;
+/************************
+ * Main alloc/init/free *
+ ************************/
+
+static int allocate_counters(struct thread_data **threads,
+ struct core_data **cores,
+ struct pkg_data **packages) {
+ unsigned int total_threads, total_cores;
+
+ if ((topology.num_threads == 0) || (topology.num_cores == 0) ||
+ (topology.num_packages == 0)) {
+ ERROR(
+ "turbostat plugin: Invalid topology: %u threads, %u cores, %u packages",
+ topology.num_threads, topology.num_cores, topology.num_packages);
+ return -1;
+ }
+
+ total_threads =
+ topology.num_threads * topology.num_cores * topology.num_packages;
+ *threads = calloc(total_threads, sizeof(struct thread_data));
+ if (*threads == NULL) {
+ ERROR("turbostat plugin: calloc failed");
+ return -1;
+ }
+
+ for (unsigned int i = 0; i < total_threads; ++i)
+ (*threads)[i].cpu_id = topology.max_cpu_id + 1;
+
+ total_cores = topology.num_cores * topology.num_packages;
+ *cores = calloc(total_cores, sizeof(struct core_data));
+ if (*cores == NULL) {
+ ERROR("turbostat plugin: calloc failed");
+ sfree(threads);
+ return -1;
+ }
+
+ *packages = calloc(topology.num_packages, sizeof(struct pkg_data));
+ if (*packages == NULL) {
+ ERROR("turbostat plugin: calloc failed");
+ sfree(cores);
+ sfree(threads);
+ return -1;
+ }
+
+ return 0;