Files
rocm-systems/src/pmc_table.c
T
Amber Lin 9e32cdb113 Don't duplicate PMC tables
Many devices have the same counter IDs for the hardware block. Devices
in the same GFX generation usually have the same block counters. No need
to list each device individually. Instead, have a table to share with all
devices that have the same counter IDs, and have separated tables for
devices that don't have the same counter IDs.

Change-Id: I857056edc6f491f61af6e9598580e5dc7d372f94
2017-03-07 11:31:23 -05:00

316 lines
11 KiB
C

/*
* Copyright © 2014 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including
* the next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "libhsakmt.h"
#include "pmc_table.h"
/* Unused counters - 163-167 */
static uint32_t gfx7_sq_counter_ids[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 168, 169, 170,
171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250
};
/* Unused counters - 166, 292 - 297 */
static uint32_t gfx8_sq_counter_ids[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133,
134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182,
183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262,
263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 298
};
/* Polaris 10/11 have the same SQ cpunter IDs but different from other gfx8's. */
/* Unused counters - 167 and 275 are *_DUMMY_LAST */
static uint32_t gfx8_pl_sq_counter_ids[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
158, 159, 160, 161, 162, 163, 164, 165, 168, 169, 170, 171, 172, 173, 174,
175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 276, 277, 278, 279, 280,
281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295
};
static struct perf_counter_block kaveri_blocks[PERFCOUNTER_BLOCKID__MAX] = {
[PERFCOUNTER_BLOCKID__SQ] = {
.num_of_slots = 8,
.num_of_counters = sizeof(gfx7_sq_counter_ids) /
sizeof(*gfx7_sq_counter_ids),
.counter_ids = gfx7_sq_counter_ids,
.counter_size_in_bits = 64,
.counter_mask = BITMASK(64)
},
};
static struct perf_counter_block carrizo_blocks[PERFCOUNTER_BLOCKID__MAX] = {
[PERFCOUNTER_BLOCKID__SQ] = {
.num_of_slots = 8,
.num_of_counters = sizeof(gfx8_sq_counter_ids) /
sizeof(*gfx8_sq_counter_ids),
.counter_ids = gfx8_sq_counter_ids,
.counter_size_in_bits = 64,
.counter_mask = BITMASK(64)
},
};
static struct perf_counter_block fiji_blocks[PERFCOUNTER_BLOCKID__MAX] = {
[PERFCOUNTER_BLOCKID__SQ] = {
.num_of_slots = 8,
.num_of_counters = sizeof(gfx8_sq_counter_ids) /
sizeof(*gfx8_sq_counter_ids),
.counter_ids = gfx8_sq_counter_ids,
.counter_size_in_bits = 64,
.counter_mask = BITMASK(64)
},
};
static struct perf_counter_block hawaii_blocks[PERFCOUNTER_BLOCKID__MAX] = {
[PERFCOUNTER_BLOCKID__SQ] = {
.num_of_slots = 8,
.num_of_counters = sizeof(gfx7_sq_counter_ids) /
sizeof(*gfx7_sq_counter_ids),
.counter_ids = gfx7_sq_counter_ids,
.counter_size_in_bits = 64,
.counter_mask = BITMASK(64)
},
};
static struct perf_counter_block polaris_blocks[PERFCOUNTER_BLOCKID__MAX] = {
[PERFCOUNTER_BLOCKID__SQ] = {
.num_of_slots = 8,
.num_of_counters = sizeof(gfx8_pl_sq_counter_ids) /
sizeof(*gfx8_pl_sq_counter_ids),
.counter_ids = gfx8_pl_sq_counter_ids,
.counter_size_in_bits = 64,
.counter_mask = BITMASK(64)
},
};
/* Current APUs only have one IOMMU. If NUMA is introduced to APUs, we'll need
* to expand the struct here to an array.
*/
static struct perf_counter_block iommu_block;
uint32_t pmc_table_get_max_concurrent(int block_id)
{
switch (block_id) {
case PERFCOUNTER_BLOCKID__IOMMUV2:
return iommu_block.num_of_slots;
default:
return 0;
}
}
static HSAKMT_STATUS
alloc_pmc_blocks_iommu(void)
{
DIR *dir;
struct dirent *dent;
const char sysfs_amdiommu_event_path[] =
"/sys/bus/event_source/devices/amd_iommu/events";
/* Counter source in IOMMU's Counter Bank Addressing register is 8 bits,
* so the biggest counter number/id possible is 0xff.
*/
const int max_counter_id = 0xff;
char path[256];
const int len = sizeof(path);
FILE *file;
int num;
char counter_id[max_counter_id + 1];
HSAKMT_STATUS ret = HSAKMT_STATUS_SUCCESS;
uint32_t *ptr;
struct perf_counter_block *block = &iommu_block;
memset(block, 0, sizeof(struct perf_counter_block));
dir = opendir(sysfs_amdiommu_event_path);
if (!dir)
goto out;
memset(counter_id, 0, max_counter_id + 1);
while ((dent = readdir(dir))) {
if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
continue;
if (snprintf(path, len, "%s/%s", sysfs_amdiommu_event_path,
dent->d_name) >= len) {
fprintf(stderr, "Increase path length.\n");
ret = HSAKMT_STATUS_NO_MEMORY;
goto out;
}
file = fopen(path, "r");
if (!file) {
ret = HSAKMT_STATUS_ERROR;
goto out;
}
if (fscanf(file, "csource=0x%x", &num) != 1) {
ret = HSAKMT_STATUS_ERROR;
fclose(file);
goto out;
}
if (num > max_counter_id)
/* This should never happen. If it does, check IOMMU driver. */
fprintf(stderr,
"Error: max_counter_id %d is set too small.\n",
max_counter_id);
else {
counter_id[num] = 1;
++block->num_of_counters;
}
fclose(file);
}
block->counter_ids = malloc(sizeof(uint32_t) * block->num_of_counters);
if (!block->counter_ids) {
ret = HSAKMT_STATUS_NO_MEMORY;
goto out;
}
ptr = block->counter_ids;
for (num = 0; num < (max_counter_id + 1); num++) {
if (counter_id[num]) {
ptr[0] = num;
++ptr;
}
}
if (snprintf(path, len, "%s/%d/%s",
"/sys/devices/virtual/kfd/kfd/topology/nodes",
0, /* IOMMU is in node 0. Change this if NUMA is introduced to APU. */
"perf/iommu/max_concurrent") >= len) {
fprintf(stderr, "Increase path length\n");
ret = HSAKMT_STATUS_NO_MEMORY;
goto out;
};
file = fopen(path, "r");
if (!file) {
ret = HSAKMT_STATUS_ERROR;
goto out;
}
if (fscanf(file, "%d", &block->num_of_slots) != 1)
ret = HSAKMT_STATUS_ERROR;
fclose(file);
out:
if (dir)
closedir(dir);
return ret;
}
HSAKMT_STATUS alloc_pmc_blocks(void)
{
return alloc_pmc_blocks_iommu();
}
void free_pmc_blocks(void)
{
if (iommu_block.counter_ids)
free(iommu_block.counter_ids);
iommu_block.counter_ids = NULL;
iommu_block.num_of_counters = 0;
}
HSAKMT_STATUS
get_block_properties(uint32_t node_id,
enum perf_block_id block_id,
struct perf_counter_block *block)
{
uint16_t dev_id = get_device_id_by_node(node_id);
enum asic_family_type asic;
if (block_id > PERFCOUNTER_BLOCKID__MAX ||
block_id < PERFCOUNTER_BLOCKID__FIRST)
return HSAKMT_STATUS_INVALID_PARAMETER;
if (block_id == PERFCOUNTER_BLOCKID__IOMMUV2) {
*block = iommu_block;
return HSAKMT_STATUS_SUCCESS;
}
if (topology_get_asic_family(dev_id, &asic) != HSAKMT_STATUS_SUCCESS)
return HSAKMT_STATUS_INVALID_PARAMETER;
switch (asic) {
case CHIP_KAVERI:
*block = kaveri_blocks[block_id];
break;
case CHIP_HAWAII:
*block = hawaii_blocks[block_id];
break;
case CHIP_CARRIZO:
*block = carrizo_blocks[block_id];
break;
case CHIP_FIJI:
*block = fiji_blocks[block_id];
break;
case CHIP_POLARIS10:
case CHIP_POLARIS11:
*block = polaris_blocks[block_id];
break;
default:
return HSAKMT_STATUS_INVALID_PARAMETER;
}
return HSAKMT_STATUS_SUCCESS;
}