Commit 3559ea81 authored by Patryk Wlazlyn's avatar Patryk Wlazlyn Committed by Len Brown

tools/power turbostat: Avoid possible memory corruption due to sparse topology IDs

Save the highest core and package id when parsing topology to
allocate enough memory when get_rapl_counters() is called with a core or
a package id as a domain.

Note that RAPL domains are per-package on Intel, but per-core on AMD.
Thus, the RAPL code effectively runs in different modes on those two
product lines.
Signed-off-by: default avatarPatryk Wlazlyn <patryk.wlazlyn@linux.intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 78464d76
...@@ -1052,6 +1052,7 @@ struct rapl_counter_info_t { ...@@ -1052,6 +1052,7 @@ struct rapl_counter_info_t {
/* struct rapl_counter_info_t for each RAPL domain */ /* struct rapl_counter_info_t for each RAPL domain */
struct rapl_counter_info_t *rapl_counter_info_perdomain; struct rapl_counter_info_t *rapl_counter_info_perdomain;
unsigned int rapl_counter_info_perdomain_size;
#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1) #define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1)
...@@ -1451,6 +1452,8 @@ struct topo_params { ...@@ -1451,6 +1452,8 @@ struct topo_params {
int allowed_cpus; int allowed_cpus;
int allowed_cores; int allowed_cores;
int max_cpu_num; int max_cpu_num;
int max_core_id;
int max_package_id;
int max_die_id; int max_die_id;
int max_node_num; int max_node_num;
int nodes_per_pkg; int nodes_per_pkg;
...@@ -3425,15 +3428,18 @@ void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci ...@@ -3425,15 +3428,18 @@ void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci
rc->scale = rci->scale[idx]; rc->scale = rci->scale[idx];
} }
int get_rapl_counters(int cpu, int domain, struct core_data *c, struct pkg_data *p) int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p)
{ {
unsigned long long perf_data[NUM_RAPL_COUNTERS + 1]; unsigned long long perf_data[NUM_RAPL_COUNTERS + 1];
struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain]; struct rapl_counter_info_t *rci;
if (debug) if (debug)
fprintf(stderr, "%s: cpu%d domain%d\n", __func__, cpu, domain); fprintf(stderr, "%s: cpu%d domain%d\n", __func__, cpu, domain);
assert(rapl_counter_info_perdomain); assert(rapl_counter_info_perdomain);
assert(domain < rapl_counter_info_perdomain_size);
rci = &rapl_counter_info_perdomain[domain];
/* /*
* If we have any perf counters to read, read them all now, in bulk * If we have any perf counters to read, read them all now, in bulk
...@@ -4257,7 +4263,7 @@ void free_fd_rapl_percpu(void) ...@@ -4257,7 +4263,7 @@ void free_fd_rapl_percpu(void)
if (!rapl_counter_info_perdomain) if (!rapl_counter_info_perdomain)
return; return;
const int num_domains = platform->has_per_core_rapl ? topo.num_cores : topo.num_packages; const int num_domains = rapl_counter_info_perdomain_size;
for (int domain_id = 0; domain_id < num_domains; ++domain_id) { for (int domain_id = 0; domain_id < num_domains; ++domain_id) {
if (rapl_counter_info_perdomain[domain_id].fd_perf != -1) if (rapl_counter_info_perdomain[domain_id].fd_perf != -1)
...@@ -4265,6 +4271,8 @@ void free_fd_rapl_percpu(void) ...@@ -4265,6 +4271,8 @@ void free_fd_rapl_percpu(void)
} }
free(rapl_counter_info_perdomain); free(rapl_counter_info_perdomain);
rapl_counter_info_perdomain = NULL;
rapl_counter_info_perdomain_size = 0;
} }
void free_all_buffers(void) void free_all_buffers(void)
...@@ -6582,17 +6590,18 @@ void linux_perf_init(void) ...@@ -6582,17 +6590,18 @@ void linux_perf_init(void)
void rapl_perf_init(void) void rapl_perf_init(void)
{ {
const int num_domains = platform->has_per_core_rapl ? topo.num_cores : topo.num_packages; const unsigned int num_domains = (platform->has_per_core_rapl ? topo.max_core_id : topo.max_package_id) + 1;
bool *domain_visited = calloc(num_domains, sizeof(bool)); bool *domain_visited = calloc(num_domains, sizeof(bool));
rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain)); rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain));
if (rapl_counter_info_perdomain == NULL) if (rapl_counter_info_perdomain == NULL)
err(-1, "calloc rapl_counter_info_percpu"); err(-1, "calloc rapl_counter_info_percpu");
rapl_counter_info_perdomain_size = num_domains;
/* /*
* Initialize rapl_counter_info_percpu * Initialize rapl_counter_info_percpu
*/ */
for (int domain_id = 0; domain_id < num_domains; ++domain_id) { for (unsigned int domain_id = 0; domain_id < num_domains; ++domain_id) {
struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id]; struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id];
rci->fd_perf = -1; rci->fd_perf = -1;
...@@ -6612,7 +6621,7 @@ void rapl_perf_init(void) ...@@ -6612,7 +6621,7 @@ void rapl_perf_init(void)
bool has_counter = 0; bool has_counter = 0;
double scale; double scale;
enum rapl_unit unit; enum rapl_unit unit;
int next_domain; unsigned int next_domain;
memset(domain_visited, 0, num_domains * sizeof(*domain_visited)); memset(domain_visited, 0, num_domains * sizeof(*domain_visited));
...@@ -6625,6 +6634,8 @@ void rapl_perf_init(void) ...@@ -6625,6 +6634,8 @@ void rapl_perf_init(void)
next_domain = next_domain =
platform->has_per_core_rapl ? cpus[cpu].physical_core_id : cpus[cpu].physical_package_id; platform->has_per_core_rapl ? cpus[cpu].physical_core_id : cpus[cpu].physical_package_id;
assert(next_domain < num_domains);
if (domain_visited[next_domain]) if (domain_visited[next_domain])
continue; continue;
...@@ -7207,6 +7218,8 @@ void topology_probe(bool startup) ...@@ -7207,6 +7218,8 @@ void topology_probe(bool startup)
if (cpus[i].thread_id == 0) if (cpus[i].thread_id == 0)
topo.num_cores++; topo.num_cores++;
} }
topo.max_core_id = max_core_id;
topo.max_package_id = max_package_id;
topo.cores_per_node = max_core_id + 1; topo.cores_per_node = max_core_id + 1;
if (debug > 1) if (debug > 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment