Commit d0f7093a authored by Len Brown's avatar Len Brown
Browse files

tools/power turbostat: Harden against unexpected values



Divide-by-zero resulted if LLC references == 0

Pull the percentage division into pct() to centralize sanity checks there.

Fixes: 88082927 ("tools/power turbostat: Print "nan" for out of range percentages")

Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 61764831
Loading
Loading
Loading
Loading
+51 −43
Original line number Diff line number Diff line
@@ -3002,22 +3002,30 @@ void print_header(char *delim)
}

/*
 * pct()
 * pct(numerator, denominator)
 *
 * If absolute value is < 1.1, return percentage
 * otherwise, return nan
 * Return sanity checked percentage (100.0 * numerator/denominotor)
 *
 * return value is appropriate for printing percentages with %f
 * while flagging some obvious erroneous values.
 * n < 0: nan
 * d <= 0: nan
 * n/d > 1.1: nan
 */
double pct(double d)
double pct(double numerator, double denominator)
{
	double retval;

	double abs = fabs(d);
	if (numerator < 0)
		return nan("");

	if (denominator <= 0)
		return nan("");

	if (abs < 1.10)
		return (100.0 * d);
	retval = 100.0 * numerator / denominator;

	if (retval > 110.0)
		return nan("");

	return retval;
}

int dump_counters(PER_THREAD_PARAMS)
@@ -3047,7 +3055,7 @@ int dump_counters(PER_THREAD_PARAMS)

		outp += sprintf(outp, "LLC refs: %lld", t->llc.references);
		outp += sprintf(outp, "LLC miss: %lld", t->llc.misses);
		outp += sprintf(outp, "LLC Hit%%: %.2f", pct((t->llc.references - t->llc.misses) / t->llc.references));
		outp += sprintf(outp, "LLC Hit%%: %.2f", pct((t->llc.references - t->llc.misses), t->llc.references));

		for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
			outp += sprintf(outp, "tADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, t->counter[i], mp->sp->path);
@@ -3262,7 +3270,7 @@ int format_counters(PER_THREAD_PARAMS)
		outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 / units * t->aperf / interval_float);

	if (DO_BIC(BIC_Busy))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->mperf / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->mperf, tsc));

	if (DO_BIC(BIC_Bzy_MHz)) {
		if (has_base_hz)
@@ -3303,7 +3311,7 @@ int format_counters(PER_THREAD_PARAMS)
			outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), t->llc.references / interval_float / 1000);

		if (DO_BIC(BIC_LLC_HIT))
			outp += sprintf(outp, fmt8, (printed++ ? delim : ""), pct((t->llc.references - t->llc.misses) / t->llc.references));
			outp += sprintf(outp, fmt8, (printed++ ? delim : ""), pct((t->llc.references - t->llc.misses), t->llc.references));
	}

	/* Added Thread Counters */
@@ -3316,7 +3324,7 @@ int format_counters(PER_THREAD_PARAMS)
			if (mp->type == COUNTER_USEC)
				outp += print_float_value(&printed, delim, t->counter[i] / interval_float / 10000);
			else
				outp += print_float_value(&printed, delim, pct(t->counter[i] / tsc));
				outp += print_float_value(&printed, delim, pct(t->counter[i], tsc));
		}
	}

@@ -3330,7 +3338,7 @@ int format_counters(PER_THREAD_PARAMS)
			if (pp->type == COUNTER_USEC)
				outp += print_float_value(&printed, delim, t->perf_counter[i] / interval_float / 10000);
			else
				outp += print_float_value(&printed, delim, pct(t->perf_counter[i] / tsc));
				outp += print_float_value(&printed, delim, pct(t->perf_counter[i], tsc));
		}
	}

@@ -3344,34 +3352,34 @@ int format_counters(PER_THREAD_PARAMS)
			break;

		case PMT_TYPE_XTAL_TIME:
			value_converted = pct(value_raw / crystal_hz / interval_float);
			value_converted = pct(value_raw / crystal_hz, interval_float);
			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
			break;

		case PMT_TYPE_TCORE_CLOCK:
			value_converted = pct(value_raw / tcore_clock_freq_hz / interval_float);
			value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);
			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
		}
	}

	/* C1 */
	if (DO_BIC(BIC_CPU_c1))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->c1 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(t->c1, tsc));

	/* print per-core data only for 1st thread in core */
	if (!is_cpu_first_thread_in_core(t, c))
		goto done;

	if (DO_BIC(BIC_CPU_c3))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c3 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c3, tsc));
	if (DO_BIC(BIC_CPU_c6))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c6 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c6, tsc));
	if (DO_BIC(BIC_CPU_c7))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c7 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->c7, tsc));

	/* Mod%c6 */
	if (DO_BIC(BIC_Mod_c6))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->mc6_us / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(c->mc6_us, tsc));

	if (DO_BIC(BIC_CoreTmp))
		outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
@@ -3387,7 +3395,7 @@ int format_counters(PER_THREAD_PARAMS)
		else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
			outp += print_decimal_value(mp->width, &printed, delim, c->counter[i]);
		else if (mp->format == FORMAT_PERCENT)
			outp += print_float_value(&printed, delim, pct(c->counter[i] / tsc));
			outp += print_float_value(&printed, delim, pct(c->counter[i], tsc));
	}

	/* Added perf Core counters */
@@ -3397,7 +3405,7 @@ int format_counters(PER_THREAD_PARAMS)
		else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
			outp += print_decimal_value(pp->width, &printed, delim, c->perf_counter[i]);
		else if (pp->format == FORMAT_PERCENT)
			outp += print_float_value(&printed, delim, pct(c->perf_counter[i] / tsc));
			outp += print_float_value(&printed, delim, pct(c->perf_counter[i], tsc));
	}

	/* Added PMT Core counters */
@@ -3410,12 +3418,12 @@ int format_counters(PER_THREAD_PARAMS)
			break;

		case PMT_TYPE_XTAL_TIME:
			value_converted = pct(value_raw / crystal_hz / interval_float);
			value_converted = pct(value_raw / crystal_hz, interval_float);
			outp += print_float_value(&printed, delim, value_converted);
			break;

		case PMT_TYPE_TCORE_CLOCK:
			value_converted = pct(value_raw / tcore_clock_freq_hz / interval_float);
			value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);
			outp += print_float_value(&printed, delim, value_converted);
		}
	}
@@ -3471,39 +3479,39 @@ int format_counters(PER_THREAD_PARAMS)
	if (DO_BIC(BIC_Totl_c0))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100 * p->pkg_wtd_core_c0 / tsc);	/* can exceed 100% */
	if (DO_BIC(BIC_Any_c0))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_core_c0 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_core_c0, tsc));
	if (DO_BIC(BIC_GFX_c0))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_gfxe_c0 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_any_gfxe_c0, tsc));
	if (DO_BIC(BIC_CPUGFX))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_both_core_gfxe_c0 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pkg_both_core_gfxe_c0, tsc));

	if (DO_BIC(BIC_Pkgpc2))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc2 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc2, tsc));
	if (DO_BIC(BIC_Pkgpc3))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc3 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc3, tsc));
	if (DO_BIC(BIC_Pkgpc6))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc6 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc6, tsc));
	if (DO_BIC(BIC_Pkgpc7))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc7 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc7, tsc));
	if (DO_BIC(BIC_Pkgpc8))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc8 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc8, tsc));
	if (DO_BIC(BIC_Pkgpc9))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc9 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc9, tsc));
	if (DO_BIC(BIC_Pkgpc10))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc10 / tsc));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->pc10, tsc));

	if (DO_BIC(BIC_Diec6))
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->die_c6 / crystal_hz / interval_float));
		outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->die_c6 / crystal_hz, interval_float));

	if (DO_BIC(BIC_CPU_LPI)) {
		if (p->cpu_lpi >= 0)
			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->cpu_lpi / 1000000.0 / interval_float));
			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->cpu_lpi / 1000000.0, interval_float));
		else
			outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));
	}
	if (DO_BIC(BIC_SYS_LPI)) {
		if (p->sys_lpi >= 0)
			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->sys_lpi / 1000000.0 / interval_float));
			outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), pct(p->sys_lpi / 1000000.0, interval_float));
		else
			outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));
	}
@@ -3543,7 +3551,7 @@ int format_counters(PER_THREAD_PARAMS)
		else if (mp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
			outp += print_decimal_value(mp->width, &printed, delim, p->counter[i]);
		else if (mp->format == FORMAT_PERCENT)
			outp += print_float_value(&printed, delim, pct(p->counter[i] / tsc));
			outp += print_float_value(&printed, delim, pct(p->counter[i], tsc));
	}

	/* Added perf Package Counters */
@@ -3555,7 +3563,7 @@ int format_counters(PER_THREAD_PARAMS)
		else if (pp->format == FORMAT_DELTA || mp->format == FORMAT_AVERAGE)
			outp += print_decimal_value(pp->width, &printed, delim, p->perf_counter[i]);
		else if (pp->format == FORMAT_PERCENT)
			outp += print_float_value(&printed, delim, pct(p->perf_counter[i] / tsc));
			outp += print_float_value(&printed, delim, pct(p->perf_counter[i], tsc));
	}

	/* Added PMT Package Counters */
@@ -3568,12 +3576,12 @@ int format_counters(PER_THREAD_PARAMS)
			break;

		case PMT_TYPE_XTAL_TIME:
			value_converted = pct(value_raw / crystal_hz / interval_float);
			value_converted = pct(value_raw / crystal_hz, interval_float);
			outp += print_float_value(&printed, delim, value_converted);
			break;

		case PMT_TYPE_TCORE_CLOCK:
			value_converted = pct(value_raw / tcore_clock_freq_hz / interval_float);
			value_converted = pct(value_raw / tcore_clock_freq_hz, interval_float);
			outp += print_float_value(&printed, delim, value_converted);
		}
	}