tools/perf/arch/x86/util/pmu.c

Source file repositories/reference/linux-study-clean/tools/perf/arch/x86/util/pmu.c

File Facts

System
Linux kernel
Corpus path
tools/perf/arch/x86/util/pmu.c
Extension
.c
Size
8843 bytes
Lines
311
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

while ((dent = io_dir__readdir(&dir)) != NULL) {
			/* Note, dent->d_type will be DT_LNK and so isn't a useful filter. */
			if (strstarts(dent->d_name, "uncore_cha_"))
				num_chas++;
		}
		close(fd);
		checked_chas = true;
	}
	return num_chas;
}

#define MAX_SNCS 6

static int uncore_cha_snc(struct perf_pmu *pmu)
{
	// CHA SNC numbers are ordered correspond to the CHAs number.
	unsigned int cha_num;
	int num_cha, chas_per_node, cha_snc;
	int snc_nodes = snc_nodes_per_l3_cache();

	if (snc_nodes <= 1)
		return 0;

	num_cha = num_chas();
	if (num_cha <= 0) {
		pr_warning("Unexpected: no CHAs found\n");
		return 0;
	}

	/* Compute SNC for PMU. */
	if (sscanf(pmu->name, "uncore_cha_%u", &cha_num) != 1) {
		pr_warning("Unexpected: unable to compute CHA number '%s'\n", pmu->name);
		return 0;
	}
	chas_per_node = num_cha / snc_nodes;
	cha_snc = cha_num / chas_per_node;

	/* Range check cha_snc. for unexpected out of bounds. */
	return cha_snc >= MAX_SNCS ? 0 : cha_snc;
}

static int uncore_imc_snc(struct perf_pmu *pmu)
{
	// Compute the IMC SNC using lookup tables.
	unsigned int imc_num;
	int snc_nodes = snc_nodes_per_l3_cache();
	const u8 snc2_map[] = {1, 1, 0, 0, 1, 1, 0, 0};
	const u8 snc3_map[] = {1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 2, 2};
	const u8 *snc_map;
	size_t snc_map_len;

	switch (snc_nodes) {
	case 2:
		snc_map = snc2_map;
		snc_map_len = ARRAY_SIZE(snc2_map);
		break;
	case 3:
		snc_map = snc3_map;
		snc_map_len = ARRAY_SIZE(snc3_map);
		break;
	default:
		/* Error or no lookup support for SNC with >3 nodes. */
		return 0;
	}

	/* Compute SNC for PMU. */
	if (sscanf(pmu->name, "uncore_imc_%u", &imc_num) != 1) {
		pr_warning("Unexpected: unable to compute IMC number '%s'\n", pmu->name);
		return 0;
	}
	if (imc_num >= snc_map_len) {
		pr_warning("Unexpected IMC %d for SNC%d mapping\n", imc_num, snc_nodes);
		return 0;
	}
	return snc_map[imc_num];
}

static int uncore_cha_imc_compute_cpu_adjust(int pmu_snc)
{
	static bool checked_cpu_adjust[MAX_SNCS];
	static int cpu_adjust[MAX_SNCS];
	struct perf_cpu_map *node_cpus;
	char node_path[] = "devices/system/node/node0/cpulist";

	/* Was adjust already computed? */
	if (checked_cpu_adjust[pmu_snc])
		return cpu_adjust[pmu_snc];

	/* SNC0 doesn't need an adjust. */
	if (pmu_snc == 0) {

Annotation

Implementation Notes