Signed-off-by: Nicolai Hähnle <nicolai.haehnle@xxxxxxx> --- src/app/top.c | 89 +++++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/src/app/top.c b/src/app/top.c index f99b7b5..40ed0ac 100644 --- a/src/app/top.c +++ b/src/app/top.c @@ -903,30 +903,31 @@ void load_options(void) } } else { // add some defaults to not be so boring top_options.vi.grbm = 1; top_options.vi.vgt = 1; top_options.vi.ta = 1; } } static struct { - char *name, *tag; + char name[32]; + char *tag; uint64_t counts[32]; int *opt, is_sensor; uint32_t addr, mask[32], cmp[32]; uint64_t addr_mask; struct umr_bitfield *bits; } stat_counters[64]; -#define ENTRY(_j, _name, _bits, _opt, _tag) do { int _i = (_j); stat_counters[_i].name = _name; stat_counters[_i].bits = _bits; stat_counters[_i].opt = _opt; stat_counters[_i].tag = _tag; } while (0) -#define ENTRY_SENSOR(_j, _name, _bits, _opt, _tag) do { int _i = (_j); stat_counters[_i].name = _name; stat_counters[_i].bits = _bits; stat_counters[_i].opt = _opt; stat_counters[_i].tag = _tag; stat_counters[_i].is_sensor = 1; } while (0) +#define ENTRY(_j, _prefix, _name, _bits, _opt, _tag) do { int _i = (_j); snprintf(stat_counters[_i].name, sizeof(stat_counters[_i].name), "%s%s", _prefix, _name); stat_counters[_i].bits = _bits; stat_counters[_i].opt = _opt; stat_counters[_i].tag = _tag; } while (0) +#define ENTRY_SENSOR(_j, _name, _bits, _opt, _tag) do { int _i = (_j); strcpy(stat_counters[_i].name, _name); stat_counters[_i].bits = _bits; stat_counters[_i].opt = _opt; stat_counters[_i].tag = _tag; stat_counters[_i].is_sensor = 1; } while (0) static void vi_handle_keys(int i) { switch(i) { case 't': top_options.vi.ta ^= 1; break; case 'g': top_options.vi.vgt ^= 1; break; case 'G': top_options.vi.gfxpwr ^= 1; break; case 'u': top_options.vi.uvd ^= 1; break; case 'c': top_options.vi.vce ^= 1; break; case 's': top_options.vi.grbm ^= 1; break; @@ -963,44 +964,59 @@ static int sriov_supported_vf(struct umr_asic *asic) return (sriov_ctrl & PCI_SRIOV_CTRL_VFE) ? sriov_num_vf : 0; } pci_offset = PCI_EXT_CAP_NEXT(pci_cfg_data); } return retval; } static void top_build_vi_program(struct umr_asic *asic) { + const char *gfx_prefix; + const char *vcn_prefix; int i, j, k; char *regname; + gfx_prefix = "mm"; + struct umr_ip_block* gfx = umr_find_ip_block(asic, "gfx", asic->options.vm_partition); + if (gfx && gfx->discoverable.maj >= 11) + gfx_prefix = "reg"; + + vcn_prefix = "mm"; + struct umr_ip_block* vcn = umr_find_ip_block(asic, "vcn", asic->options.vm_partition); + if (vcn && ((vcn->discoverable.maj == 2 && vcn->discoverable.min >= 6) || vcn->discoverable.maj >= 4)) + vcn_prefix = "reg"; + stat_counters[0].bits = &stat_grbm_bits[0]; stat_counters[0].opt = &top_options.vi.grbm; stat_counters[0].tag = "GRBM"; - stat_counters[1].opt = &top_options.vi.grbm; - stat_counters[1].tag = stat_counters[0].tag; - stat_counters[1].name = "mmGRBM_STATUS2"; - stat_counters[1].bits = &stat_grbm2_bits[0]; + // which SE to read ... + if (options.use_bank == 1) + snprintf(stat_counters[0].name, sizeof(stat_counters[0].name), gfx_prefix, "GRBM_STATUS_SE%d", options.bank.grbm.se); + else + snprintf(stat_counters[0].name, sizeof(stat_counters[0].name), gfx_prefix, "GRBM_STATUS"); + + i = 1; - i = 2; + ENTRY(i++, gfx_prefix, "GRBM_STATUS2", &stat_grbm2_bits[0], &top_options.vi.grbm, "GRBM"); top_options.sriov.active_vf = -1; top_options.sriov.num_vf = sriov_supported_vf(asic); if (top_options.sriov.num_vf != 0) { stat_counters[i].is_sensor = 3; - ENTRY(i++, "mmRLC_GPU_IOV_ACTIVE_FCN_ID", &stat_rlc_iov_bits[0], + ENTRY(i++, gfx_prefix, "RLC_GPU_IOV_ACTIVE_FCN_ID", &stat_rlc_iov_bits[0], &top_options.vi.grbm, "GPU_IOV"); } if (asic->config.gfx.family > 110) - ENTRY(i++, "mmRLC_GPM_STAT", &stat_rlc_gpm_bits[0], &top_options.vi.gfxpwr, "GFX PWR"); + ENTRY(i++, gfx_prefix, "RLC_GPM_STAT", &stat_rlc_gpm_bits[0], &top_options.vi.gfxpwr, "GFX PWR"); // sensors if (asic->family >= FAMILY_NV) { ENTRY_SENSOR(i++, "GFX_SCLK", &stat_nv_sensor_bits[0], &top_options.vi.sensors, "Sensors"); } else if (asic->config.gfx.family == 141 || asic->config.gfx.family == 142) { // Arctic Island Family/Raven ENTRY_SENSOR(i++, "GFX_SCLK", &stat_ai_sensor_bits[0], &top_options.vi.sensors, "Sensors"); } else if (asic->config.gfx.family == 135) { // Carrizo/Stoney family ENTRY_SENSOR(i++, "GFX_SCLK", &stat_carrizo_sensor_bits[0], &top_options.vi.sensors, "Sensors"); @@ -1013,80 +1029,71 @@ static void top_build_vi_program(struct umr_asic *asic) } else if (asic->config.gfx.family == 120) { // CIK ENTRY_SENSOR(i++, "GFX_SCLK", &stat_cik_sensor_bits[0], &top_options.vi.sensors, "Sensors"); } else if (asic->config.gfx.family == 110) { // SI ENTRY_SENSOR(i++, "GFX_SCLK", &stat_si_sensor_bits[0], &top_options.vi.sensors, "Sensors"); } sensor_bits = stat_counters[i-1].bits; // More GFX bits - ENTRY(i++, "mmTA_STATUS", &stat_ta_bits[0], &top_options.vi.ta, "TA"); + ENTRY(i++, gfx_prefix, "TA_STATUS", &stat_ta_bits[0], &top_options.vi.ta, "TA"); // VGT bits only valid for gfx7..9 if (asic->family < FAMILY_NV) - ENTRY(i++, "mmVGT_CNTL_STATUS", &stat_vgt_bits[0], &top_options.vi.vgt, "VGT"); + ENTRY(i++, gfx_prefix, "VGT_CNTL_STATUS", &stat_vgt_bits[0], &top_options.vi.vgt, "VGT"); // UVD registers if (asic->family < FAMILY_AI) - ENTRY(i++, "mmSRBM_STATUS", &stat_srbm_status_uvd_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, gfx_prefix, "SRBM_STATUS", &stat_srbm_status_uvd_bits[0], &top_options.vi.uvd, "UVD"); k = i; - ENTRY(i++, "mmUVD_CGC_STATUS", &stat_uvdclk_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_CGC_STATUS", &stat_uvdclk_bits[0], &top_options.vi.uvd, "UVD"); // set PG flag for all UVD registers for (; k < i; k++) { stat_counters[k].addr_mask = REG_USE_PG_LOCK; // UVD requires PG lock } k = j = i; - ENTRY(i++, "mmUVD_PGFSM_READ_TILE1", &stat_uvd_pgfsm1_bits[0], &top_options.vi.uvd, "UVD"); - ENTRY(i++, "mmUVD_PGFSM_READ_TILE2", &stat_uvd_pgfsm2_bits[0], &top_options.vi.uvd, "UVD"); - ENTRY(i++, "mmUVD_PGFSM_READ_TILE3", &stat_uvd_pgfsm3_bits[0], &top_options.vi.uvd, "UVD"); - ENTRY(i++, "mmUVD_PGFSM_READ_TILE4", &stat_uvd_pgfsm4_bits[0], &top_options.vi.uvd, "UVD"); - ENTRY(i++, "mmUVD_PGFSM_READ_TILE5", &stat_uvd_pgfsm5_bits[0], &top_options.vi.uvd, "UVD"); - ENTRY(i++, "mmUVD_PGFSM_READ_TILE6", &stat_uvd_pgfsm6_bits[0], &top_options.vi.uvd, "UVD"); - ENTRY(i++, "mmUVD_PGFSM_READ_TILE7", &stat_uvd_pgfsm7_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE1", &stat_uvd_pgfsm1_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE2", &stat_uvd_pgfsm2_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE3", &stat_uvd_pgfsm3_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE4", &stat_uvd_pgfsm4_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE5", &stat_uvd_pgfsm5_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE6", &stat_uvd_pgfsm6_bits[0], &top_options.vi.uvd, "UVD"); + ENTRY(i++, vcn_prefix, "UVD_PGFSM_READ_TILE7", &stat_uvd_pgfsm7_bits[0], &top_options.vi.uvd, "UVD"); // set compare/mask for UVD TILE registers for (; j < i; j++) { stat_counters[j].cmp[0] = 0; stat_counters[j].mask[0] = 3; stat_counters[j].addr_mask = REG_USE_PG_LOCK; // require PG lock } // VCE registers if (asic->family < FAMILY_AI) - ENTRY(i++, "mmSRBM_STATUS2", &stat_srbm_status2_vce_bits[0], &top_options.vi.vce, "VCE"); + ENTRY(i++, gfx_prefix, "SRBM_STATUS2", &stat_srbm_status2_vce_bits[0], &top_options.vi.vce, "VCE"); k = i; // set PG flag for all VCE registers for (; k < i; k++) { stat_counters[k].addr_mask = REG_USE_PG_LOCK; // VCE requires PG lock } // memory hub k = i; if (asic->family < FAMILY_AI) - ENTRY(i++, "mmMC_HUB_MISC_STATUS", &stat_mc_hub_bits[0], &top_options.vi.memory_hub, "MC HUB"); + ENTRY(i++, gfx_prefix, "MC_HUB_MISC_STATUS", &stat_mc_hub_bits[0], &top_options.vi.memory_hub, "MC HUB"); // SDMA k = i; if (asic->family < FAMILY_AI) - ENTRY(i++, "mmSRBM_STATUS2", &stat_sdma_bits[0], &top_options.vi.sdma, "SDMA"); - - // which SE to read ... - regname = calloc(1, 64); - if (options.use_bank == 1) - snprintf(regname, 63, "mmGRBM_STATUS_SE%d", options.bank.grbm.se); - else - snprintf(regname, 63, "mmGRBM_STATUS"); - - stat_counters[0].name = regname; + ENTRY(i++, gfx_prefix, "SRBM_STATUS2", &stat_sdma_bits[0], &top_options.vi.sdma, "SDMA"); top_options.handle_key = vi_handle_keys; top_options.helptext = "(u)vd v(c)e (G)FX_PWR (s)GRBM (t)a v(g)t (m)emory_hub \n" "s(d)ma se(n)sors\n"; } static void toggle_logger(void) { @@ -1094,21 +1101,21 @@ static void toggle_logger(void) top_options.logger ^= 1; if (top_options.logger) { char *p, name[512]; if (!(p = getenv("UMR_LOGGER"))) p = getenv("HOME"); sprintf(name, "%s/umr.log", p); logfile = fopen(name, "a"); fprintf(logfile, "Time (seconds),"); - for (i = 0; stat_counters[i].name; i++) + for (i = 0; stat_counters[i].name[0]; i++) if (top_options.all || *stat_counters[i].opt) for (j = 0; stat_counters[i].bits[j].regname != 0; j++) fprintf(logfile, "%s.%s,", stat_counters[i].tag, stat_counters[i].bits[j].regname); fprintf(logfile, "\n"); } else { if (logfile) fclose(logfile); logfile = NULL; } } @@ -1163,25 +1170,25 @@ void umr_top(struct umr_asic *asic) if (getenv("HOSTNAME")) strcpy(hostname, getenv("HOSTNAME")); // init stats memset(&stat_counters, 0, sizeof stat_counters); load_options(); // select an architecture ... top_build_vi_program(asic); // add DRM info - for (i = 0; stat_counters[i].name; i++); - ENTRY(i, "DRM", &stat_drm_bits[0], &top_options.drm, "DRM"); + for (i = 0; stat_counters[i].name[0]; i++); + ENTRY(i, "", "DRM", &stat_drm_bits[0], &top_options.drm, "DRM"); stat_counters[i].is_sensor = 2; - for (i = 0; stat_counters[i].name; i++) { + for (i = 0; stat_counters[i].name[0]; i++) { if (stat_counters[i].is_sensor == 0) grab_bits(stat_counters[i].name, asic, stat_counters[i].bits, &stat_counters[i].addr); else if (stat_counters[i].is_sensor == 3) grab_addr(stat_counters[i].name, asic, stat_counters[i].bits, &stat_counters[i].addr); } sensor_thread_quit = 0; // start thread to grab sensor data if (pthread_create(&sensor_thread, NULL, gpu_sensor_thread, asic)) { @@ -1205,27 +1212,27 @@ void umr_top(struct umr_asic *asic) // setup loop if (top_options.high_precision) rep = 1000; else rep = 100; req.tv_sec = 0; req.tv_nsec = 1000000000/rep; // 10ms ts = 0; while (!top_options.quit) { - for (i = 0; stat_counters[i].name; i++) + for (i = 0; stat_counters[i].name[0]; i++) memset(stat_counters[i].counts, 0, sizeof(stat_counters[i].counts[0])*32); for (i = 0; i < (int)rep / (top_options.high_frequency ? 10 : 1); i++) { if (!top_options.sriov.num_vf || top_options.sriov.active_vf < 0 || top_options.sriov.active_vf == get_active_vf(asic, stat_counters[2].addr)) { - for (j = 0; stat_counters[j].name; j++) { + for (j = 0; stat_counters[j].name[0]; j++) { if (top_options.all || *stat_counters[j].opt) { if (stat_counters[j].is_sensor == 0) parse_bits(asic, stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask); else if (i == 0 && stat_counters[j].is_sensor == 1) // only parse sensors on first go-around per display parse_sensors(asic, stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask); else if (i == 0 && stat_counters[j].is_sensor == 2) // only parse drm on first go-around per display parse_drm(asic, stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask); else if (stat_counters[j].is_sensor == 3) parse_iov(asic, stat_counters[j].addr, stat_counters[j].bits, stat_counters[j].counts, stat_counters[j].mask, stat_counters[j].cmp, stat_counters[j].addr_mask); } @@ -1286,34 +1293,34 @@ void umr_top(struct umr_asic *asic) tt = time(NULL); printw("(%s[%s]) %s%s -- %s", hostname, asic->asicname, top_options.logger ? "(logger enabled) " : "", top_options.high_frequency ? (top_options.high_precision ? "(sample @ 1ms, report @ 100ms)" : "(sample @ 10ms, report @ 100ms)") : (top_options.high_precision ? "(sample @ 1ms, report @ 1000ms)" : "(sample @ 10ms, report @ 1000ms)"), ctime(&tt)); // figure out padding - for (i = maxstrlen = 0; stat_counters[i].name; i++) + for (i = maxstrlen = 0; stat_counters[i].name[0]; i++) if (top_options.all || *stat_counters[i].opt) for (j = 0; stat_counters[i].bits[j].regname; j++) if (stat_counters[i].bits[j].start != 255 && (k = strlen(stat_counters[i].bits[j].regname)) > maxstrlen) maxstrlen = k; snprintf(namefmt, sizeof(namefmt)-1, "%%%ds => ", maxstrlen + 1); print_j = 0; if (logfile != NULL) { struct timespec tp; clock_gettime(CLOCK_MONOTONIC, &tp); fprintf(logfile, "%f,", ((double)tp.tv_sec * 1000000000.0 + tp.tv_nsec) / 1000000000.0); } - for (i = 0; stat_counters[i].name; i++) { + for (i = 0; stat_counters[i].name[0]; i++) { if (top_options.all || *stat_counters[i].opt) { if (logfile != NULL) { for (j = 0; stat_counters[i].bits[j].regname != 0; j++) { if (stat_counters[i].bits[j].start != 255) fprintf(logfile, "%llu,", (unsigned long long)stat_counters[i].counts[j]); } } if (!i || strcmp(stat_counters[i-1].tag, stat_counters[i].tag)) { if (print_j & (top_options.wide ? 3 : 1)) printw("\n"); -- 2.40.0