Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3384c786 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'x86/topology' into perf/core, to prepare for new patches



Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 6a9f4efe eb876fbc
Loading
Loading
Loading
Loading
+33 −15
Original line number Diff line number Diff line
@@ -12,6 +12,12 @@ physical_package_id:
	socket number, but the actual value is architecture and platform
	dependent.

die_id:

	the CPU die ID of cpuX. Typically it is the hardware platform's
	identifier (rather than the kernel's).  The actual value is
	architecture and platform dependent.

core_id:

	the CPU core ID of cpuX. Typically it is the hardware platform's
@@ -30,25 +36,33 @@ drawer_id:
	identifier (rather than the kernel's).	The actual value is
	architecture and platform dependent.

thread_siblings:
core_cpus:

	internal kernel map of cpuX's hardware threads within the same
	core as cpuX.
	internal kernel map of CPUs within the same core.
	(deprecated name: "thread_siblings")

thread_siblings_list:
core_cpus_list:

	human-readable list of cpuX's hardware threads within the same
	core as cpuX.
	human-readable list of CPUs within the same core.
	(deprecated name: "thread_siblings_list");

core_siblings:
package_cpus:

	internal kernel map of cpuX's hardware threads within the same
	physical_package_id.
	internal kernel map of the CPUs sharing the same physical_package_id.
	(deprecated name: "core_siblings")

core_siblings_list:
package_cpus_list:

	human-readable list of cpuX's hardware threads within the same
	physical_package_id.
	human-readable list of CPUs sharing the same physical_package_id.
	(deprecated name: "core_siblings_list")

die_cpus:

	internal kernel map of CPUs within the same die.

die_cpus_list:

	human-readable list of CPUs within the same die.

book_siblings:

@@ -81,11 +95,13 @@ For an architecture to support this feature, it must define some of
these macros in include/asm-XXX/topology.h::

	#define topology_physical_package_id(cpu)
	#define topology_die_id(cpu)
	#define topology_core_id(cpu)
	#define topology_book_id(cpu)
	#define topology_drawer_id(cpu)
	#define topology_sibling_cpumask(cpu)
	#define topology_core_cpumask(cpu)
	#define topology_die_cpumask(cpu)
	#define topology_book_cpumask(cpu)
	#define topology_drawer_cpumask(cpu)

@@ -99,9 +115,11 @@ provides default definitions for any of the above macros that are
not defined by include/asm-XXX/topology.h:

1) topology_physical_package_id: -1
2) topology_core_id: 0
3) topology_sibling_cpumask: just the given CPU
4) topology_core_cpumask: just the given CPU
2) topology_die_id: -1
3) topology_core_id: 0
4) topology_sibling_cpumask: just the given CPU
5) topology_core_cpumask: just the given CPU
6) topology_die_cpumask: just the given CPU

For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
default definitions for topology_book_id() and topology_book_cpumask().
+4 −0
Original line number Diff line number Diff line
@@ -49,6 +49,10 @@ Package-related topology information in the kernel:

    The number of cores in a package. This information is retrieved via CPUID.

  - cpuinfo_x86.x86_max_dies:

    The number of dies in a package. This information is retrieved via CPUID.

  - cpuinfo_x86.phys_proc_id:

    The physical ID of the package. This information is retrieved via CPUID
+10 −4
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
			return -EINVAL;
		event->hw.event_base = pkg_msr[cfg].msr;
		cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
				      topology_core_cpumask(event->cpu));
				      topology_die_cpumask(event->cpu));
	} else {
		return -ENOENT;
	}
@@ -385,7 +385,7 @@ static int cstate_cpu_exit(unsigned int cpu)
	if (has_cstate_pkg &&
	    cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) {

		target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
		target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
		/* Migrate events if there is a valid target */
		if (target < nr_cpu_ids) {
			cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
@@ -414,7 +414,7 @@ static int cstate_cpu_init(unsigned int cpu)
	 * in the package cpu mask as the designated reader.
	 */
	target = cpumask_any_and(&cstate_pkg_cpu_mask,
				 topology_core_cpumask(cpu));
				 topology_die_cpumask(cpu));
	if (has_cstate_pkg && target >= nr_cpu_ids)
		cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);

@@ -663,7 +663,13 @@ static int __init cstate_init(void)
	}

	if (has_cstate_pkg) {
		err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);
		if (topology_max_die_per_package() > 1) {
			err = perf_pmu_register(&cstate_pkg_pmu,
						"cstate_die", -1);
		} else {
			err = perf_pmu_register(&cstate_pkg_pmu,
						cstate_pkg_pmu.name, -1);
		}
		if (err) {
			has_cstate_pkg = false;
			pr_info("Failed to register cstate pkg pmu\n");
+10 −10
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ struct rapl_pmu {

struct rapl_pmus {
	struct pmu		pmu;
	unsigned int		maxpkg;
	unsigned int		maxdie;
	struct rapl_pmu		*pmus[];
};

@@ -162,13 +162,13 @@ static u64 rapl_timer_ms;

static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
{
	unsigned int pkgid = topology_logical_package_id(cpu);
	unsigned int dieid = topology_logical_die_id(cpu);

	/*
	 * The unsigned check also catches the '-1' return value for non
	 * existent mappings in the topology map.
	 */
	return pkgid < rapl_pmus->maxpkg ? rapl_pmus->pmus[pkgid] : NULL;
	return dieid < rapl_pmus->maxdie ? rapl_pmus->pmus[dieid] : NULL;
}

static inline u64 rapl_read_counter(struct perf_event *event)
@@ -572,7 +572,7 @@ static int rapl_cpu_offline(unsigned int cpu)

	pmu->cpu = -1;
	/* Find a new cpu to collect rapl events */
	target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
	target = cpumask_any_but(topology_die_cpumask(cpu), cpu);

	/* Migrate rapl events to the new target */
	if (target < nr_cpu_ids) {
@@ -599,14 +599,14 @@ static int rapl_cpu_online(unsigned int cpu)
		pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
		rapl_hrtimer_init(pmu);

		rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
		rapl_pmus->pmus[topology_logical_die_id(cpu)] = pmu;
	}

	/*
	 * Check if there is an online cpu in the package which collects rapl
	 * events already.
	 */
	target = cpumask_any_and(&rapl_cpu_mask, topology_core_cpumask(cpu));
	target = cpumask_any_and(&rapl_cpu_mask, topology_die_cpumask(cpu));
	if (target < nr_cpu_ids)
		return 0;

@@ -669,22 +669,22 @@ static void cleanup_rapl_pmus(void)
{
	int i;

	for (i = 0; i < rapl_pmus->maxpkg; i++)
	for (i = 0; i < rapl_pmus->maxdie; i++)
		kfree(rapl_pmus->pmus[i]);
	kfree(rapl_pmus);
}

static int __init init_rapl_pmus(void)
{
	int maxpkg = topology_max_packages();
	int maxdie = topology_max_packages() * topology_max_die_per_package();
	size_t size;

	size = sizeof(*rapl_pmus) + maxpkg * sizeof(struct rapl_pmu *);
	size = sizeof(*rapl_pmus) + maxdie * sizeof(struct rapl_pmu *);
	rapl_pmus = kzalloc(size, GFP_KERNEL);
	if (!rapl_pmus)
		return -ENOMEM;

	rapl_pmus->maxpkg		= maxpkg;
	rapl_pmus->maxdie		= maxdie;
	rapl_pmus->pmu.attr_groups	= rapl_attr_groups;
	rapl_pmus->pmu.task_ctx_nr	= perf_invalid_context;
	rapl_pmus->pmu.event_init	= rapl_pmu_event_init;
+41 −39
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ struct pci_driver *uncore_pci_driver;
DEFINE_RAW_SPINLOCK(pci2phy_map_lock);
struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head);
struct pci_extra_dev *uncore_extra_pci_dev;
static int max_packages;
static int max_dies;

/* mask of cpus that collect uncore events */
static cpumask_t uncore_cpu_mask;
@@ -101,13 +101,13 @@ ssize_t uncore_event_show(struct kobject *kobj,

struct intel_uncore_box *uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
{
	unsigned int pkgid = topology_logical_package_id(cpu);
	unsigned int dieid = topology_logical_die_id(cpu);

	/*
	 * The unsigned check also catches the '-1' return value for non
	 * existent mappings in the topology map.
	 */
	return pkgid < max_packages ? pmu->boxes[pkgid] : NULL;
	return dieid < max_dies ? pmu->boxes[dieid] : NULL;
}

u64 uncore_msr_read_counter(struct intel_uncore_box *box, struct perf_event *event)
@@ -312,7 +312,7 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
	uncore_pmu_init_hrtimer(box);
	box->cpu = -1;
	box->pci_phys_id = -1;
	box->pkgid = -1;
	box->dieid = -1;

	/* set default hrtimer timeout */
	box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
@@ -827,10 +827,10 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)

static void uncore_free_boxes(struct intel_uncore_pmu *pmu)
{
	int pkg;
	int die;

	for (pkg = 0; pkg < max_packages; pkg++)
		kfree(pmu->boxes[pkg]);
	for (die = 0; die < max_dies; die++)
		kfree(pmu->boxes[die]);
	kfree(pmu->boxes);
}

@@ -867,7 +867,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type, bool setid)
	if (!pmus)
		return -ENOMEM;

	size = max_packages * sizeof(struct intel_uncore_box *);
	size = max_dies * sizeof(struct intel_uncore_box *);

	for (i = 0; i < type->num_boxes; i++) {
		pmus[i].func_id	= setid ? i : -1;
@@ -937,20 +937,21 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
	struct intel_uncore_type *type;
	struct intel_uncore_pmu *pmu = NULL;
	struct intel_uncore_box *box;
	int phys_id, pkg, ret;
	int phys_id, die, ret;

	phys_id = uncore_pcibus_to_physid(pdev->bus);
	if (phys_id < 0)
		return -ENODEV;

	pkg = topology_phys_to_logical_pkg(phys_id);
	if (pkg < 0)
	die = (topology_max_die_per_package() > 1) ? phys_id :
					topology_phys_to_logical_pkg(phys_id);
	if (die < 0)
		return -EINVAL;

	if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
		int idx = UNCORE_PCI_DEV_IDX(id->driver_data);

		uncore_extra_pci_dev[pkg].dev[idx] = pdev;
		uncore_extra_pci_dev[die].dev[idx] = pdev;
		pci_set_drvdata(pdev, NULL);
		return 0;
	}
@@ -989,7 +990,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
		pmu = &type->pmus[UNCORE_PCI_DEV_IDX(id->driver_data)];
	}

	if (WARN_ON_ONCE(pmu->boxes[pkg] != NULL))
	if (WARN_ON_ONCE(pmu->boxes[die] != NULL))
		return -EINVAL;

	box = uncore_alloc_box(type, NUMA_NO_NODE);
@@ -1003,13 +1004,13 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id

	atomic_inc(&box->refcnt);
	box->pci_phys_id = phys_id;
	box->pkgid = pkg;
	box->dieid = die;
	box->pci_dev = pdev;
	box->pmu = pmu;
	uncore_box_init(box);
	pci_set_drvdata(pdev, box);

	pmu->boxes[pkg] = box;
	pmu->boxes[die] = box;
	if (atomic_inc_return(&pmu->activeboxes) > 1)
		return 0;

@@ -1017,7 +1018,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
	ret = uncore_pmu_register(pmu);
	if (ret) {
		pci_set_drvdata(pdev, NULL);
		pmu->boxes[pkg] = NULL;
		pmu->boxes[die] = NULL;
		uncore_box_exit(box);
		kfree(box);
	}
@@ -1028,16 +1029,17 @@ static void uncore_pci_remove(struct pci_dev *pdev)
{
	struct intel_uncore_box *box;
	struct intel_uncore_pmu *pmu;
	int i, phys_id, pkg;
	int i, phys_id, die;

	phys_id = uncore_pcibus_to_physid(pdev->bus);

	box = pci_get_drvdata(pdev);
	if (!box) {
		pkg = topology_phys_to_logical_pkg(phys_id);
		die = (topology_max_die_per_package() > 1) ? phys_id :
					topology_phys_to_logical_pkg(phys_id);
		for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
			if (uncore_extra_pci_dev[pkg].dev[i] == pdev) {
				uncore_extra_pci_dev[pkg].dev[i] = NULL;
			if (uncore_extra_pci_dev[die].dev[i] == pdev) {
				uncore_extra_pci_dev[die].dev[i] = NULL;
				break;
			}
		}
@@ -1050,7 +1052,7 @@ static void uncore_pci_remove(struct pci_dev *pdev)
		return;

	pci_set_drvdata(pdev, NULL);
	pmu->boxes[box->pkgid] = NULL;
	pmu->boxes[box->dieid] = NULL;
	if (atomic_dec_return(&pmu->activeboxes) == 0)
		uncore_pmu_unregister(pmu);
	uncore_box_exit(box);
@@ -1062,7 +1064,7 @@ static int __init uncore_pci_init(void)
	size_t size;
	int ret;

	size = max_packages * sizeof(struct pci_extra_dev);
	size = max_dies * sizeof(struct pci_extra_dev);
	uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);
	if (!uncore_extra_pci_dev) {
		ret = -ENOMEM;
@@ -1109,11 +1111,11 @@ static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu,
{
	struct intel_uncore_pmu *pmu = type->pmus;
	struct intel_uncore_box *box;
	int i, pkg;
	int i, die;

	pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
	die = topology_logical_die_id(old_cpu < 0 ? new_cpu : old_cpu);
	for (i = 0; i < type->num_boxes; i++, pmu++) {
		box = pmu->boxes[pkg];
		box = pmu->boxes[die];
		if (!box)
			continue;

@@ -1146,13 +1148,13 @@ static int uncore_event_cpu_offline(unsigned int cpu)
	struct intel_uncore_type *type, **types = uncore_msr_uncores;
	struct intel_uncore_pmu *pmu;
	struct intel_uncore_box *box;
	int i, pkg, target;
	int i, die, target;

	/* Check if exiting cpu is used for collecting uncore events */
	if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
		goto unref;
	/* Find a new cpu to collect uncore events */
	target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
	target = cpumask_any_but(topology_die_cpumask(cpu), cpu);

	/* Migrate uncore events to the new target */
	if (target < nr_cpu_ids)
@@ -1165,12 +1167,12 @@ static int uncore_event_cpu_offline(unsigned int cpu)

unref:
	/* Clear the references */
	pkg = topology_logical_package_id(cpu);
	die = topology_logical_die_id(cpu);
	for (; *types; types++) {
		type = *types;
		pmu = type->pmus;
		for (i = 0; i < type->num_boxes; i++, pmu++) {
			box = pmu->boxes[pkg];
			box = pmu->boxes[die];
			if (box && atomic_dec_return(&box->refcnt) == 0)
				uncore_box_exit(box);
		}
@@ -1179,7 +1181,7 @@ static int uncore_event_cpu_offline(unsigned int cpu)
}

static int allocate_boxes(struct intel_uncore_type **types,
			 unsigned int pkg, unsigned int cpu)
			 unsigned int die, unsigned int cpu)
{
	struct intel_uncore_box *box, *tmp;
	struct intel_uncore_type *type;
@@ -1192,20 +1194,20 @@ static int allocate_boxes(struct intel_uncore_type **types,
		type = *types;
		pmu = type->pmus;
		for (i = 0; i < type->num_boxes; i++, pmu++) {
			if (pmu->boxes[pkg])
			if (pmu->boxes[die])
				continue;
			box = uncore_alloc_box(type, cpu_to_node(cpu));
			if (!box)
				goto cleanup;
			box->pmu = pmu;
			box->pkgid = pkg;
			box->dieid = die;
			list_add(&box->active_list, &allocated);
		}
	}
	/* Install them in the pmus */
	list_for_each_entry_safe(box, tmp, &allocated, active_list) {
		list_del_init(&box->active_list);
		box->pmu->boxes[pkg] = box;
		box->pmu->boxes[die] = box;
	}
	return 0;

@@ -1222,10 +1224,10 @@ static int uncore_event_cpu_online(unsigned int cpu)
	struct intel_uncore_type *type, **types = uncore_msr_uncores;
	struct intel_uncore_pmu *pmu;
	struct intel_uncore_box *box;
	int i, ret, pkg, target;
	int i, ret, die, target;

	pkg = topology_logical_package_id(cpu);
	ret = allocate_boxes(types, pkg, cpu);
	die = topology_logical_die_id(cpu);
	ret = allocate_boxes(types, die, cpu);
	if (ret)
		return ret;

@@ -1233,7 +1235,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
		type = *types;
		pmu = type->pmus;
		for (i = 0; i < type->num_boxes; i++, pmu++) {
			box = pmu->boxes[pkg];
			box = pmu->boxes[die];
			if (box && atomic_inc_return(&box->refcnt) == 1)
				uncore_box_init(box);
		}
@@ -1243,7 +1245,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
	 * Check if there is an online cpu in the package
	 * which collects uncore events already.
	 */
	target = cpumask_any_and(&uncore_cpu_mask, topology_core_cpumask(cpu));
	target = cpumask_any_and(&uncore_cpu_mask, topology_die_cpumask(cpu));
	if (target < nr_cpu_ids)
		return 0;

@@ -1418,7 +1420,7 @@ static int __init intel_uncore_init(void)
	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
		return -ENODEV;

	max_packages = topology_max_packages();
	max_dies = topology_max_packages() * topology_max_die_per_package();

	uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
	if (uncore_init->pci_init) {
Loading