hsakmt: move 'counter_id' array to heap

local variable 'counter_id' exceeded the max single
use of stack, thus move to heap to prevent overflow

also, use of a contiguous memory block for 2D array
to reduce space complexity, add error messages for
NO_MEMORY exits and check MAX_COUNTER limit for IDs

Change-Id: Id0249ca767a336b31c759c693a82d3f5c950a2fa
Signed-off-by: Apurv Mishra <apurv.mishra@amd.com>


[ROCm/ROCR-Runtime commit: ecf57310ca]
This commit is contained in:
Apurv Mishra
2025-01-06 13:15:30 -05:00
förälder e004ab79f5
incheckning 4ea98d22c4
+49 -15
Visa fil
@@ -345,7 +345,10 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtPmcRegisterTrace(HSAuint32 NodeId,
struct perf_trace *trace = NULL;
uint32_t concurrent_limit;
const uint32_t MAX_COUNTERS = 512;
uint64_t counter_id[PERFCOUNTER_BLOCKID__MAX][MAX_COUNTERS];
/* Declare performance counter ID 2D array as a contiguous block */
uint64_t *counter_id = malloc(
PERFCOUNTER_BLOCKID__MAX * MAX_COUNTERS * sizeof(uint64_t));
uint32_t num_counters[PERFCOUNTER_BLOCKID__MAX] = {0};
uint32_t block, num_blocks = 0, total_counters = 0;
uint64_t *counter_id_ptr;
@@ -353,32 +356,48 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtPmcRegisterTrace(HSAuint32 NodeId,
pr_debug("[%s] Number of counters %d\n", __func__, NumberOfCounters);
if (!counter_props)
if (counter_id == NULL) {
pr_err("Failed to allocate memory for counter_id. Requested %zu bytes.\n",
PERFCOUNTER_BLOCKID__MAX * MAX_COUNTERS * sizeof(uint64_t));
return HSAKMT_STATUS_NO_MEMORY;
}
if (!counter_props) {
pr_err("Profiling is not available, counter_props is NULL.\n");
goto no_memory_exit;
}
if (!Counters || !TraceRoot || NumberOfCounters == 0)
return HSAKMT_STATUS_INVALID_PARAMETER;
goto invalid_parameter_exit;
if (hsakmt_validate_nodeid(NodeId, &gpu_id) != HSAKMT_STATUS_SUCCESS)
if (hsakmt_validate_nodeid(NodeId, &gpu_id) != HSAKMT_STATUS_SUCCESS) {
free(counter_id);
return HSAKMT_STATUS_INVALID_NODE_UNIT;
}
if (NumberOfCounters > MAX_COUNTERS) {
pr_err("MAX_COUNTERS is too small for %d.\n",
NumberOfCounters);
return HSAKMT_STATUS_NO_MEMORY;
pr_err("MAX_COUNTERS is too small for %d.\n", NumberOfCounters);
goto no_memory_exit;
}
/* Calculating the minimum buffer size */
for (i = 0; i < NumberOfCounters; i++) {
if (Counters[i].BlockIndex >= PERFCOUNTER_BLOCKID__MAX)
return HSAKMT_STATUS_INVALID_PARAMETER;
goto invalid_parameter_exit;
/* Only privileged counters need to register */
if (Counters[i].Type > HSA_PROFILE_TYPE_PRIVILEGED_STREAMING)
continue;
min_buf_size += Counters[i].CounterSizeInBits/BITS_PER_BYTE;
/* j: the first blank entry in the block to record counter_id */
j = num_counters[Counters[i].BlockIndex];
counter_id[Counters[i].BlockIndex][j] = Counters[i].CounterId;
/* Make sure counter_id stays within bounds */
if (j >= MAX_COUNTERS) {
pr_err("Counter ID exceeded MAX_COUNTERS for block %d.\n",
Counters[i].BlockIndex);
goto invalid_parameter_exit;
}
/* Initialize counter_id */
counter_id[Counters[i].BlockIndex * MAX_COUNTERS + j] = Counters[i].CounterId;
num_counters[Counters[i].BlockIndex]++;
total_counters++;
}
@@ -392,17 +411,17 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtPmcRegisterTrace(HSAuint32 NodeId,
concurrent_limit = get_block_concurrent_limit(NodeId, i);
if (!concurrent_limit) {
pr_err("Invalid block ID: %d\n", i);
return HSAKMT_STATUS_INVALID_PARAMETER;
goto invalid_parameter_exit;
}
if (num_counters[i] > concurrent_limit) {
pr_err("Counters exceed the limit.\n");
return HSAKMT_STATUS_INVALID_PARAMETER;
goto invalid_parameter_exit;
}
num_blocks++;
}
if (!num_blocks)
return HSAKMT_STATUS_INVALID_PARAMETER;
goto invalid_parameter_exit;
/* Now we have sorted blocks/counters information in
* num_counters[block_id] and counter_id[block_id][]. Allocate trace
@@ -413,8 +432,14 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtPmcRegisterTrace(HSAuint32 NodeId,
+ sizeof(uint64_t) * total_counters
+ sizeof(int) * total_counters,
1);
if (!trace)
return HSAKMT_STATUS_NO_MEMORY;
if (!trace) {
pr_err("Failed to allocate memory for trace. Requested %zu bytes.\n",
sizeof(struct perf_trace)
+ sizeof(struct perf_trace_block) * num_blocks
+ sizeof(uint64_t) * total_counters
+ sizeof(int) * total_counters);
goto no_memory_exit;
}
/* Allocated area is partitioned as:
* +---------------------------------+ trace
@@ -449,7 +474,7 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtPmcRegisterTrace(HSAuint32 NodeId,
trace->blocks[block].counter_id = counter_id_ptr;
/* Fill in counter IDs to the counter_id array. */
for (j = 0; j < num_counters[i]; j++)
trace->blocks[block].counter_id[j] = counter_id[i][j];
trace->blocks[block].counter_id[j] = counter_id[i * MAX_COUNTERS + j];
trace->blocks[block].perf_event_fd = fd_ptr;
/* how many counters to trace */
trace->blocks[block].num_counters = num_counters[i];
@@ -470,7 +495,16 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtPmcRegisterTrace(HSAuint32 NodeId,
TraceRoot->TraceId = PORT_VPTR_TO_UINT64(trace);
free(trace);
free(counter_id);
return HSAKMT_STATUS_SUCCESS;
no_memory_exit:
free(counter_id);
return HSAKMT_STATUS_NO_MEMORY;
invalid_parameter_exit:
free(counter_id);
return HSAKMT_STATUS_INVALID_PARAMETER;
}
/* Unregisters a set of (HW) counters used for tracing/profiling */