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

Commit 222a21d2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'x86-topology-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 topology updates from Ingo Molnar:
 "Implement multi-die topology support on Intel CPUs and expose the die
  topology to user-space tooling, by Len Brown, Kan Liang and Zhang Rui.

  These changes should have no effect on the kernel's existing
  understanding of topologies, i.e. there should be no behavioral impact
  on cache, NUMA, scheduler, perf and other topologies and overall
  system performance"

* 'x86-topology-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/intel/rapl: Cosmetic rename internal variables in response to multi-die/pkg support
  perf/x86/intel/uncore: Cosmetic renames in response to multi-die/pkg support
  hwmon/coretemp: Cosmetic: Rename internal variables to zones from packages
  thermal/x86_pkg_temp_thermal: Cosmetic: Rename internal variables to zones from packages
  perf/x86/intel/cstate: Support multi-die/package
  perf/x86/intel/rapl: Support multi-die/package
  perf/x86/intel/uncore: Support multi-die/package
  topology: Create core_cpus and die_cpus sysfs attributes
  topology: Create package_cpus sysfs attribute
  hwmon/coretemp: Support multi-die/package
  powercap/intel_rapl: Update RAPL domain name and debug messages
  thermal/x86_pkg_temp_thermal: Support multi-die/package
  powercap/intel_rapl: Support multi-die/package
  powercap/intel_rapl: Simplify rapl_find_package()
  x86/topology: Define topology_logical_die_id()
  x86/topology: Define topology_die_id()
  cpu/topology: Export die_id
  x86/topology: Create topology_max_die_per_package()
  x86/topology: Add CPUID.1F multi-die/package support
parents 8faef712 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;

@@ -1419,7 +1421,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