arch/x86/events/intel/uncore_discovery.c

Source file repositories/reference/linux-study-clean/arch/x86/events/intel/uncore_discovery.c

File Facts

System
Linux kernel
Corpus path
arch/x86/events/intel/uncore_discovery.c
Extension
.c
Size
19992 bytes
Lines
811
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

while ((dvsec = pci_find_next_ext_capability(dev, dvsec, UNCORE_EXT_CAP_ID_DISCOVERY))) {
			pci_read_config_dword(dev, dvsec + UNCORE_DISCOVERY_DVSEC_OFFSET, &val);
			entry_id = val & UNCORE_DISCOVERY_DVSEC_ID_MASK;
			if (entry_id != UNCORE_DISCOVERY_DVSEC_ID_PMON)
				continue;

			pci_read_config_dword(dev, dvsec + UNCORE_DISCOVERY_DVSEC2_OFFSET, &val);

			if (val & ~UNCORE_DISCOVERY_DVSEC2_BIR_MASK) {
				ret = false;
				goto err;
			}
			bar_offset = UNCORE_DISCOVERY_BIR_BASE +
				     (val & UNCORE_DISCOVERY_DVSEC2_BIR_MASK) * UNCORE_DISCOVERY_BIR_STEP;

			die = get_device_die_id(dev);
			if ((die < 0) || (die >= uncore_max_dies()))
				continue;

			parse_discovery_table(domain, dev, die, bar_offset, &parsed);
		}
	}

	/* None of the discovery tables are available */
	if (!parsed)
		ret = false;
err:
	pci_dev_put(dev);

	return ret;
}

static bool uncore_discovery_msr(struct uncore_discovery_domain *domain)
{
	unsigned long *die_mask;
	bool parsed = false;
	int cpu, die;
	u64 base;

	die_mask = kcalloc(BITS_TO_LONGS(uncore_max_dies()),
			   sizeof(unsigned long), GFP_KERNEL);
	if (!die_mask)
		return false;

	for_each_online_cpu(cpu) {
		die = topology_logical_die_id(cpu);
		if (__test_and_set_bit(die, die_mask))
			continue;

		if (rdmsrq_safe_on_cpu(cpu, domain->discovery_base, &base))
			continue;

		if (!base)
			continue;

		__parse_discovery_table(domain, base, die, &parsed);
	}

	kfree(die_mask);
	return parsed;
}

bool uncore_discovery(struct uncore_plat_init *init)
{
	struct uncore_discovery_domain *domain;
	bool ret = false;
	int i;

	for (i = 0; i < UNCORE_DISCOVERY_DOMAINS; i++) {
		domain = &init->domain[i];
		if (domain->discovery_base) {
			cpus_read_lock();

			if (!domain->base_is_pci)
				ret |= uncore_discovery_msr(domain);
			else
				ret |= uncore_discovery_pci(domain);

			cpus_read_unlock();
		}
	}

	return ret;
}

void intel_uncore_clear_discovery_tables(void)
{
	struct intel_uncore_discovery_type *type, *next;
	struct intel_uncore_discovery_unit *pos;
	struct rb_node *node;

Annotation

Implementation Notes