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

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

Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 6a9f4efe eb876fbc
...@@ -12,6 +12,12 @@ physical_package_id: ...@@ -12,6 +12,12 @@ physical_package_id:
socket number, but the actual value is architecture and platform socket number, but the actual value is architecture and platform
dependent. 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: core_id:
the CPU core ID of cpuX. Typically it is the hardware platform's the CPU core ID of cpuX. Typically it is the hardware platform's
...@@ -30,25 +36,33 @@ drawer_id: ...@@ -30,25 +36,33 @@ drawer_id:
identifier (rather than the kernel's). The actual value is identifier (rather than the kernel's). The actual value is
architecture and platform dependent. architecture and platform dependent.
thread_siblings: core_cpus:
internal kernel map of cpuX's hardware threads within the same internal kernel map of CPUs within the same core.
core as cpuX. (deprecated name: "thread_siblings")
thread_siblings_list: core_cpus_list:
human-readable list of cpuX's hardware threads within the same human-readable list of CPUs within the same core.
core as cpuX. (deprecated name: "thread_siblings_list");
core_siblings: package_cpus:
internal kernel map of cpuX's hardware threads within the same internal kernel map of the CPUs sharing the same physical_package_id.
physical_package_id. (deprecated name: "core_siblings")
core_siblings_list: package_cpus_list:
human-readable list of cpuX's hardware threads within the same human-readable list of CPUs sharing the same physical_package_id.
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: book_siblings:
...@@ -81,11 +95,13 @@ For an architecture to support this feature, it must define some of ...@@ -81,11 +95,13 @@ For an architecture to support this feature, it must define some of
these macros in include/asm-XXX/topology.h:: these macros in include/asm-XXX/topology.h::
#define topology_physical_package_id(cpu) #define topology_physical_package_id(cpu)
#define topology_die_id(cpu)
#define topology_core_id(cpu) #define topology_core_id(cpu)
#define topology_book_id(cpu) #define topology_book_id(cpu)
#define topology_drawer_id(cpu) #define topology_drawer_id(cpu)
#define topology_sibling_cpumask(cpu) #define topology_sibling_cpumask(cpu)
#define topology_core_cpumask(cpu) #define topology_core_cpumask(cpu)
#define topology_die_cpumask(cpu)
#define topology_book_cpumask(cpu) #define topology_book_cpumask(cpu)
#define topology_drawer_cpumask(cpu) #define topology_drawer_cpumask(cpu)
...@@ -99,9 +115,11 @@ provides default definitions for any of the above macros that are ...@@ -99,9 +115,11 @@ provides default definitions for any of the above macros that are
not defined by include/asm-XXX/topology.h: not defined by include/asm-XXX/topology.h:
1) topology_physical_package_id: -1 1) topology_physical_package_id: -1
2) topology_core_id: 0 2) topology_die_id: -1
3) topology_sibling_cpumask: just the given CPU 3) topology_core_id: 0
4) topology_core_cpumask: just the given CPU 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 For architectures that don't support books (CONFIG_SCHED_BOOK) there are no
default definitions for topology_book_id() and topology_book_cpumask(). default definitions for topology_book_id() and topology_book_cpumask().
......
...@@ -49,6 +49,10 @@ Package-related topology information in the kernel: ...@@ -49,6 +49,10 @@ Package-related topology information in the kernel:
The number of cores in a package. This information is retrieved via CPUID. 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: - cpuinfo_x86.phys_proc_id:
The physical ID of the package. This information is retrieved via CPUID The physical ID of the package. This information is retrieved via CPUID
......
...@@ -302,7 +302,7 @@ static int cstate_pmu_event_init(struct perf_event *event) ...@@ -302,7 +302,7 @@ static int cstate_pmu_event_init(struct perf_event *event)
return -EINVAL; return -EINVAL;
event->hw.event_base = pkg_msr[cfg].msr; event->hw.event_base = pkg_msr[cfg].msr;
cpu = cpumask_any_and(&cstate_pkg_cpu_mask, cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
topology_core_cpumask(event->cpu)); topology_die_cpumask(event->cpu));
} else { } else {
return -ENOENT; return -ENOENT;
} }
...@@ -385,7 +385,7 @@ static int cstate_cpu_exit(unsigned int cpu) ...@@ -385,7 +385,7 @@ static int cstate_cpu_exit(unsigned int cpu)
if (has_cstate_pkg && if (has_cstate_pkg &&
cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) { 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 */ /* Migrate events if there is a valid target */
if (target < nr_cpu_ids) { if (target < nr_cpu_ids) {
cpumask_set_cpu(target, &cstate_pkg_cpu_mask); cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
...@@ -414,7 +414,7 @@ static int cstate_cpu_init(unsigned int cpu) ...@@ -414,7 +414,7 @@ static int cstate_cpu_init(unsigned int cpu)
* in the package cpu mask as the designated reader. * in the package cpu mask as the designated reader.
*/ */
target = cpumask_any_and(&cstate_pkg_cpu_mask, target = cpumask_any_and(&cstate_pkg_cpu_mask,
topology_core_cpumask(cpu)); topology_die_cpumask(cpu));
if (has_cstate_pkg && target >= nr_cpu_ids) if (has_cstate_pkg && target >= nr_cpu_ids)
cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask); cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
...@@ -663,7 +663,13 @@ static int __init cstate_init(void) ...@@ -663,7 +663,13 @@ static int __init cstate_init(void)
} }
if (has_cstate_pkg) { 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) { if (err) {
has_cstate_pkg = false; has_cstate_pkg = false;
pr_info("Failed to register cstate pkg pmu\n"); pr_info("Failed to register cstate pkg pmu\n");
......
...@@ -149,7 +149,7 @@ struct rapl_pmu { ...@@ -149,7 +149,7 @@ struct rapl_pmu {
struct rapl_pmus { struct rapl_pmus {
struct pmu pmu; struct pmu pmu;
unsigned int maxpkg; unsigned int maxdie;
struct rapl_pmu *pmus[]; struct rapl_pmu *pmus[];
}; };
...@@ -162,13 +162,13 @@ static u64 rapl_timer_ms; ...@@ -162,13 +162,13 @@ static u64 rapl_timer_ms;
static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu) 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 * The unsigned check also catches the '-1' return value for non
* existent mappings in the topology map. * 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) static inline u64 rapl_read_counter(struct perf_event *event)
...@@ -572,7 +572,7 @@ static int rapl_cpu_offline(unsigned int cpu) ...@@ -572,7 +572,7 @@ static int rapl_cpu_offline(unsigned int cpu)
pmu->cpu = -1; pmu->cpu = -1;
/* Find a new cpu to collect rapl events */ /* 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 */ /* Migrate rapl events to the new target */
if (target < nr_cpu_ids) { if (target < nr_cpu_ids) {
...@@ -599,14 +599,14 @@ static int rapl_cpu_online(unsigned int cpu) ...@@ -599,14 +599,14 @@ static int rapl_cpu_online(unsigned int cpu)
pmu->timer_interval = ms_to_ktime(rapl_timer_ms); pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
rapl_hrtimer_init(pmu); 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 * Check if there is an online cpu in the package which collects rapl
* events already. * 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) if (target < nr_cpu_ids)
return 0; return 0;
...@@ -669,22 +669,22 @@ static void cleanup_rapl_pmus(void) ...@@ -669,22 +669,22 @@ static void cleanup_rapl_pmus(void)
{ {
int i; 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->pmus[i]);
kfree(rapl_pmus); kfree(rapl_pmus);
} }
static int __init init_rapl_pmus(void) 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_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); rapl_pmus = kzalloc(size, GFP_KERNEL);
if (!rapl_pmus) if (!rapl_pmus)
return -ENOMEM; return -ENOMEM;
rapl_pmus->maxpkg = maxpkg; rapl_pmus->maxdie = maxdie;
rapl_pmus->pmu.attr_groups = rapl_attr_groups; rapl_pmus->pmu.attr_groups = rapl_attr_groups;
rapl_pmus->pmu.task_ctx_nr = perf_invalid_context; rapl_pmus->pmu.task_ctx_nr = perf_invalid_context;
rapl_pmus->pmu.event_init = rapl_pmu_event_init; rapl_pmus->pmu.event_init = rapl_pmu_event_init;
......
...@@ -15,7 +15,7 @@ struct pci_driver *uncore_pci_driver; ...@@ -15,7 +15,7 @@ struct pci_driver *uncore_pci_driver;
DEFINE_RAW_SPINLOCK(pci2phy_map_lock); DEFINE_RAW_SPINLOCK(pci2phy_map_lock);
struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head); struct list_head pci2phy_map_head = LIST_HEAD_INIT(pci2phy_map_head);
struct pci_extra_dev *uncore_extra_pci_dev; struct pci_extra_dev *uncore_extra_pci_dev;
static int max_packages; static int max_dies;
/* mask of cpus that collect uncore events */ /* mask of cpus that collect uncore events */
static cpumask_t uncore_cpu_mask; static cpumask_t uncore_cpu_mask;
...@@ -101,13 +101,13 @@ ssize_t uncore_event_show(struct kobject *kobj, ...@@ -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) 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 * The unsigned check also catches the '-1' return value for non
* existent mappings in the topology map. * 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) 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, ...@@ -312,7 +312,7 @@ static struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
uncore_pmu_init_hrtimer(box); uncore_pmu_init_hrtimer(box);
box->cpu = -1; box->cpu = -1;
box->pci_phys_id = -1; box->pci_phys_id = -1;
box->pkgid = -1; box->dieid = -1;
/* set default hrtimer timeout */ /* set default hrtimer timeout */
box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL; box->hrtimer_duration = UNCORE_PMU_HRTIMER_INTERVAL;
...@@ -827,10 +827,10 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu) ...@@ -827,10 +827,10 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu)
static void uncore_free_boxes(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++) for (die = 0; die < max_dies; die++)
kfree(pmu->boxes[pkg]); kfree(pmu->boxes[die]);
kfree(pmu->boxes); kfree(pmu->boxes);
} }
...@@ -867,7 +867,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type, bool setid) ...@@ -867,7 +867,7 @@ static int __init uncore_type_init(struct intel_uncore_type *type, bool setid)
if (!pmus) if (!pmus)
return -ENOMEM; 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++) { for (i = 0; i < type->num_boxes; i++) {
pmus[i].func_id = setid ? i : -1; 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 ...@@ -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_type *type;
struct intel_uncore_pmu *pmu = NULL; struct intel_uncore_pmu *pmu = NULL;
struct intel_uncore_box *box; struct intel_uncore_box *box;
int phys_id, pkg, ret; int phys_id, die, ret;
phys_id = uncore_pcibus_to_physid(pdev->bus); phys_id = uncore_pcibus_to_physid(pdev->bus);
if (phys_id < 0) if (phys_id < 0)
return -ENODEV; return -ENODEV;
pkg = topology_phys_to_logical_pkg(phys_id); die = (topology_max_die_per_package() > 1) ? phys_id :
if (pkg < 0) topology_phys_to_logical_pkg(phys_id);
if (die < 0)
return -EINVAL; return -EINVAL;
if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) { if (UNCORE_PCI_DEV_TYPE(id->driver_data) == UNCORE_EXTRA_PCI_DEV) {
int idx = UNCORE_PCI_DEV_IDX(id->driver_data); 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); pci_set_drvdata(pdev, NULL);
return 0; return 0;
} }
...@@ -989,7 +990,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -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)]; 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; return -EINVAL;
box = uncore_alloc_box(type, NUMA_NO_NODE); 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 ...@@ -1003,13 +1004,13 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
atomic_inc(&box->refcnt); atomic_inc(&box->refcnt);
box->pci_phys_id = phys_id; box->pci_phys_id = phys_id;
box->pkgid = pkg; box->dieid = die;
box->pci_dev = pdev; box->pci_dev = pdev;
box->pmu = pmu; box->pmu = pmu;
uncore_box_init(box); uncore_box_init(box);
pci_set_drvdata(pdev, box); pci_set_drvdata(pdev, box);
pmu->boxes[pkg] = box; pmu->boxes[die] = box;
if (atomic_inc_return(&pmu->activeboxes) > 1) if (atomic_inc_return(&pmu->activeboxes) > 1)
return 0; return 0;
...@@ -1017,7 +1018,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id ...@@ -1017,7 +1018,7 @@ static int uncore_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id
ret = uncore_pmu_register(pmu); ret = uncore_pmu_register(pmu);
if (ret) { if (ret) {
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
pmu->boxes[pkg] = NULL; pmu->boxes[die] = NULL;
uncore_box_exit(box); uncore_box_exit(box);
kfree(box); kfree(box);
} }
...@@ -1028,16 +1029,17 @@ static void uncore_pci_remove(struct pci_dev *pdev) ...@@ -1028,16 +1029,17 @@ static void uncore_pci_remove(struct pci_dev *pdev)
{ {
struct intel_uncore_box *box; struct intel_uncore_box *box;
struct intel_uncore_pmu *pmu; struct intel_uncore_pmu *pmu;
int i, phys_id, pkg; int i, phys_id, die;
phys_id = uncore_pcibus_to_physid(pdev->bus); phys_id = uncore_pcibus_to_physid(pdev->bus);
box = pci_get_drvdata(pdev); box = pci_get_drvdata(pdev);
if (!box) { 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++) { for (i = 0; i < UNCORE_EXTRA_PCI_DEV_MAX; i++) {
if (uncore_extra_pci_dev[pkg].dev[i] == pdev) { if (uncore_extra_pci_dev[die].dev[i] == pdev) {
uncore_extra_pci_dev[pkg].dev[i] = NULL; uncore_extra_pci_dev[die].dev[i] = NULL;
break; break;
} }
} }
...@@ -1050,7 +1052,7 @@ static void uncore_pci_remove(struct pci_dev *pdev) ...@@ -1050,7 +1052,7 @@ static void uncore_pci_remove(struct pci_dev *pdev)
return; return;
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
pmu->boxes[box->pkgid] = NULL; pmu->boxes[box->dieid] = NULL;
if (atomic_dec_return(&pmu->activeboxes) == 0) if (atomic_dec_return(&pmu->activeboxes) == 0)
uncore_pmu_unregister(pmu); uncore_pmu_unregister(pmu);
uncore_box_exit(box); uncore_box_exit(box);
...@@ -1062,7 +1064,7 @@ static int __init uncore_pci_init(void) ...@@ -1062,7 +1064,7 @@ static int __init uncore_pci_init(void)
size_t size; size_t size;
int ret; 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); uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);
if (!uncore_extra_pci_dev) { if (!uncore_extra_pci_dev) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1109,11 +1111,11 @@ static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_cpu, ...@@ -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_pmu *pmu = type->pmus;
struct intel_uncore_box *box; 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++) { for (i = 0; i < type->num_boxes; i++, pmu++) {
box = pmu->boxes[pkg]; box = pmu->boxes[die];
if (!box) if (!box)
continue; continue;
...@@ -1146,13 +1148,13 @@ static int uncore_event_cpu_offline(unsigned int cpu) ...@@ -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_type *type, **types = uncore_msr_uncores;
struct intel_uncore_pmu *pmu; struct intel_uncore_pmu *pmu;
struct intel_uncore_box *box; struct intel_uncore_box *box;
int i, pkg, target; int i, die, target;
/* Check if exiting cpu is used for collecting uncore events */ /* Check if exiting cpu is used for collecting uncore events */
if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask)) if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
goto unref; goto unref;
/* Find a new cpu to collect uncore events */ /* 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 */ /* Migrate uncore events to the new target */
if (target < nr_cpu_ids) if (target < nr_cpu_ids)
...@@ -1165,12 +1167,12 @@ static int uncore_event_cpu_offline(unsigned int cpu) ...@@ -1165,12 +1167,12 @@ static int uncore_event_cpu_offline(unsigned int cpu)
unref: unref:
/* Clear the references */ /* Clear the references */
pkg = topology_logical_package_id(cpu); die = topology_logical_die_id(cpu);
for (; *types; types++) { for (; *types; types++) {
type = *types; type = *types;
pmu = type->pmus; pmu = type->pmus;
for (i = 0; i < type->num_boxes; i++, pmu++) { 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) if (box && atomic_dec_return(&box->refcnt) == 0)
uncore_box_exit(box); uncore_box_exit(box);
} }
...@@ -1179,7 +1181,7 @@ static int uncore_event_cpu_offline(unsigned int cpu) ...@@ -1179,7 +1181,7 @@ static int uncore_event_cpu_offline(unsigned int cpu)
} }
static int allocate_boxes(struct intel_uncore_type **types, 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_box *box, *tmp;
struct intel_uncore_type *type; struct intel_uncore_type *type;
...@@ -1192,20 +1194,20 @@ static int allocate_boxes(struct intel_uncore_type **types, ...@@ -1192,20 +1194,20 @@ static int allocate_boxes(struct intel_uncore_type **types,
type = *types; type = *types;
pmu = type->pmus; pmu = type->pmus;
for (i = 0; i < type->num_boxes; i++, pmu++) { for (i = 0; i < type->num_boxes; i++, pmu++) {
if (pmu->boxes[pkg]) if (pmu->boxes[die])
continue; continue;
box = uncore_alloc_box(type, cpu_to_node(cpu)); box = uncore_alloc_box(type, cpu_to_node(cpu));
if (!box) if (!box)
goto cleanup; goto cleanup;
box->pmu = pmu; box->pmu = pmu;
box->pkgid = pkg; box->dieid = die;
list_add(&box->active_list, &allocated); list_add(&box->active_list, &allocated);
} }
} }
/* Install them in the pmus */ /* Install them in the pmus */
list_for_each_entry_safe(box, tmp, &allocated, active_list) { list_for_each_entry_safe(box, tmp, &allocated, active_list) {
list_del_init(&box->active_list); list_del_init(&box->active_list);
box->pmu->boxes[pkg] = box; box->pmu->boxes[die] = box;
} }
return 0; return 0;
...@@ -1222,10 +1224,10 @@ static int uncore_event_cpu_online(unsigned int cpu) ...@@ -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_type *type, **types = uncore_msr_uncores;
struct intel_uncore_pmu *pmu; struct intel_uncore_pmu *pmu;
struct intel_uncore_box *box; struct intel_uncore_box *box;
int i, ret, pkg, target; int i, ret, die, target;
pkg = topology_logical_package_id(cpu); die = topology_logical_die_id(cpu);
ret = allocate_boxes(types, pkg, cpu); ret = allocate_boxes(types, die, cpu);
if (ret) if (ret)
return ret; return ret;
...@@ -1233,7 +1235,7 @@ static int uncore_event_cpu_online(unsigned int cpu) ...@@ -1233,7 +1235,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
type = *types; type = *types;
pmu = type->pmus; pmu = type->pmus;
for (i = 0; i < type->num_boxes; i++, pmu++) { 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) if (box && atomic_inc_return(&box->refcnt) == 1)
uncore_box_init(box); uncore_box_init(box);
} }
...@@ -1243,7 +1245,7 @@ static int uncore_event_cpu_online(unsigned int cpu) ...@@ -1243,7 +1245,7 @@ static int uncore_event_cpu_online(unsigned int cpu)
* Check if there is an online cpu in the package * Check if there is an online cpu in the package
* which collects uncore events already. * 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) if (target < nr_cpu_ids)
return 0; return 0;
...@@ -1418,7 +1420,7 @@ static int __init intel_uncore_init(void) ...@@ -1418,7 +1420,7 @@ static int __init intel_uncore_init(void)
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
return -ENODEV; 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; uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
if (uncore_init->pci_init) { if (uncore_init->pci_init) {
......
...@@ -108,7 +108,7 @@ struct intel_uncore_extra_reg { ...@@ -108,7 +108,7 @@ struct intel_uncore_extra_reg {
struct intel_uncore_box { struct intel_uncore_box {
int pci_phys_id; int pci_phys_id;
int pkgid; /* Logical package ID */ int dieid; /* Logical die ID */
int n_active; /* number of active events */ int n_active; /* number of active events */
int n_events; int n_events;
int cpu; /* cpu to collect events */ int cpu; /* cpu to collect events */
...@@ -467,7 +467,7 @@ static inline void uncore_box_exit(struct intel_uncore_box *box) ...@@ -467,7 +467,7 @@ static inline void uncore_box_exit(struct intel_uncore_box *box)
static inline bool uncore_box_is_fake(struct intel_uncore_box *box) static inline bool uncore_box_is_fake(struct intel_uncore_box *box)
{ {
return (box->pkgid < 0); return (box->dieid < 0);
} }
static inline struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event) static inline struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
......
...@@ -1058,8 +1058,8 @@ static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_eve ...@@ -1058,8 +1058,8 @@ static void snbep_qpi_enable_event(struct intel_uncore_box *box, struct perf_eve
if (reg1->idx != EXTRA_REG_NONE) { if (reg1->idx != EXTRA_REG_NONE) {
int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER; int idx = box->pmu->pmu_idx + SNBEP_PCI_QPI_PORT0_FILTER;
int pkg = box->pkgid; int die = box->dieid;
struct pci_dev *filter_pdev = uncore_extra_pci_dev[pkg].dev[idx]; struct pci_dev *filter_pdev = uncore_extra_pci_dev[die].dev[idx];
if (filter_pdev) { if (filter_pdev) {
pci_write_config_dword(filter_pdev, reg1->reg, pci_write_config_dword(filter_pdev, reg1->reg,
......
...@@ -105,7 +105,7 @@ struct cpuinfo_x86 { ...@@ -105,7 +105,7 @@ struct cpuinfo_x86 {
int x86_power; int x86_power;
unsigned long loops_per_jiffy; unsigned long loops_per_jiffy;
/* cpuid returned max cores value: */ /* cpuid returned max cores value: */
u16 x86_max_cores; u16 x86_max_cores;
u16 apicid; u16 apicid;
u16 initial_apicid; u16 initial_apicid;
u16 x86_clflush_size; u16 x86_clflush_size;
...@@ -117,6 +117,8 @@ struct cpuinfo_x86 { ...@@ -117,6 +117,8 @@ struct cpuinfo_x86 {
u16 logical_proc_id; u16 logical_proc_id;
/* Core id: */ /* Core id: */
u16 cpu_core_id; u16 cpu_core_id;
u16 cpu_die_id;
u16 logical_die_id;
/* Index into per_cpu list: */ /* Index into per_cpu list: */
u16 cpu_index; u16 cpu_index;
u32 microcode; u32 microcode;
......
...@@ -23,6 +23,7 @@ extern unsigned int num_processors; ...@@ -23,6 +23,7 @@ extern unsigned int num_processors;
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map); DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_map);
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map);
/* cpus sharing the last level cache: */ /* cpus sharing the last level cache: */
DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); DECLARE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id); DECLARE_PER_CPU_READ_MOSTLY(u16, cpu_llc_id);
......
...@@ -106,15 +106,25 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu); ...@@ -106,15 +106,25 @@ extern const struct cpumask *cpu_coregroup_mask(int cpu);
#define topology_logical_package_id(cpu) (cpu_data(cpu).logical_proc_id) #define topology_logical_package_id(cpu) (cpu_data(cpu).logical_proc_id)
#define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id) #define topology_physical_package_id(cpu) (cpu_data(cpu).phys_proc_id)
#define topology_logical_die_id(cpu) (cpu_data(cpu).logical_die_id)
#define topology_die_id(cpu) (cpu_data(cpu).cpu_die_id)
#define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id) #define topology_core_id(cpu) (cpu_data(cpu).cpu_core_id)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define topology_die_cpumask(cpu) (per_cpu(cpu_die_map, cpu))
#define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu)) #define topology_core_cpumask(cpu) (per_cpu(cpu_core_map, cpu))
#define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu)) #define topology_sibling_cpumask(cpu) (per_cpu(cpu_sibling_map, cpu))
extern unsigned int __max_logical_packages; extern unsigned int __max_logical_packages;
#define topology_max_packages() (__max_logical_packages) #define topology_max_packages() (__max_logical_packages)
extern unsigned int __max_die_per_package;
static inline int topology_max_die_per_package(void)
{
return __max_die_per_package;
}
extern int __max_smt_threads; extern int __max_smt_threads;
static inline int topology_max_smt_threads(void) static inline int topology_max_smt_threads(void)
...@@ -123,14 +133,21 @@ static inline int topology_max_smt_threads(void) ...@@ -123,14 +133,21 @@ static inline int topology_max_smt_threads(void)
} }
int topology_update_package_map(unsigned int apicid, unsigned int cpu); int topology_update_package_map(unsigned int apicid, unsigned int cpu);
int topology_update_die_map(unsigned int dieid, unsigned int cpu);
int topology_phys_to_logical_pkg(unsigned int pkg); int topology_phys_to_logical_pkg(unsigned int pkg);
int topology_phys_to_logical_die(unsigned int die, unsigned int cpu);
bool topology_is_primary_thread(unsigned int cpu); bool topology_is_primary_thread(unsigned int cpu);
bool topology_smt_supported(void); bool topology_smt_supported(void);
#else #else
#define topology_max_packages() (1) #define topology_max_packages() (1)
static inline int static inline int
topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; } topology_update_package_map(unsigned int apicid, unsigned int cpu) { return 0; }
static inline int
topology_update_die_map(unsigned int dieid, unsigned int cpu) { return 0; }
static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; } static inline int topology_phys_to_logical_pkg(unsigned int pkg) { return 0; }
static inline int topology_phys_to_logical_die(unsigned int die,
unsigned int cpu) { return 0; }
static inline int topology_max_die_per_package(void) { return 1; }
static inline int topology_max_smt_threads(void) { return 1; } static inline int topology_max_smt_threads(void) { return 1; }
static inline bool topology_is_primary_thread(unsigned int cpu) { return true; } static inline bool topology_is_primary_thread(unsigned int cpu) { return true; }
static inline bool topology_smt_supported(void) { return false; } static inline bool topology_smt_supported(void) { return false; }
......
...@@ -1299,6 +1299,7 @@ static void validate_apic_and_package_id(struct cpuinfo_x86 *c) ...@@ -1299,6 +1299,7 @@ static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
cpu, apicid, c->initial_apicid); cpu, apicid, c->initial_apicid);
} }
BUG_ON(topology_update_package_map(c->phys_proc_id, cpu)); BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
#else #else
c->logical_proc_id = 0; c->logical_proc_id = 0;
#endif #endif
......
...@@ -15,33 +15,66 @@ ...@@ -15,33 +15,66 @@
/* leaf 0xb SMT level */ /* leaf 0xb SMT level */
#define SMT_LEVEL 0 #define SMT_LEVEL 0
/* leaf 0xb sub-leaf types */ /* extended topology sub-leaf types */
#define INVALID_TYPE 0 #define INVALID_TYPE 0
#define SMT_TYPE 1 #define SMT_TYPE 1
#define CORE_TYPE 2 #define CORE_TYPE 2
#define DIE_TYPE 5
#define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff) #define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
#define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f) #define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
#define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff) #define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff)
int detect_extended_topology_early(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
unsigned int __max_die_per_package __read_mostly = 1;
EXPORT_SYMBOL(__max_die_per_package);
/*
* Check if given CPUID extended toplogy "leaf" is implemented
*/
static int check_extended_topology_leaf(int leaf)
{
unsigned int eax, ebx, ecx, edx; unsigned int eax, ebx, ecx, edx;
if (c->cpuid_level < 0xb) cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
return -1; return -1;
cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); return 0;
}
/*
* Return best CPUID Extended Toplogy Leaf supported
*/
static int detect_extended_topology_leaf(struct cpuinfo_x86 *c)
{
if (c->cpuid_level >= 0x1f) {
if (check_extended_topology_leaf(0x1f) == 0)
return 0x1f;
}
/* if (c->cpuid_level >= 0xb) {
* check if the cpuid leaf 0xb is actually implemented. if (check_extended_topology_leaf(0xb) == 0)
*/ return 0xb;
if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE)) }
return -1;
}
#endif
int detect_extended_topology_early(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
unsigned int eax, ebx, ecx, edx;
int leaf;
leaf = detect_extended_topology_leaf(c);
if (leaf < 0)
return -1; return -1;
set_cpu_cap(c, X86_FEATURE_XTOPOLOGY); set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
/* /*
* initial apic id, which also represents 32-bit extended x2apic id. * initial apic id, which also represents 32-bit extended x2apic id.
*/ */
...@@ -52,7 +85,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c) ...@@ -52,7 +85,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
} }
/* /*
* Check for extended topology enumeration cpuid leaf 0xb and if it * Check for extended topology enumeration cpuid leaf, and if it
* exists, use it for populating initial_apicid and cpu topology * exists, use it for populating initial_apicid and cpu topology
* detection. * detection.
*/ */
...@@ -60,22 +93,28 @@ int detect_extended_topology(struct cpuinfo_x86 *c) ...@@ -60,22 +93,28 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
{ {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
unsigned int eax, ebx, ecx, edx, sub_index; unsigned int eax, ebx, ecx, edx, sub_index;
unsigned int ht_mask_width, core_plus_mask_width; unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width;
unsigned int core_select_mask, core_level_siblings; unsigned int core_select_mask, core_level_siblings;
unsigned int die_select_mask, die_level_siblings;
int leaf;
if (detect_extended_topology_early(c) < 0) leaf = detect_extended_topology_leaf(c);
if (leaf < 0)
return -1; return -1;
/* /*
* Populate HT related information from sub-leaf level 0. * Populate HT related information from sub-leaf level 0.
*/ */
cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx); cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
c->initial_apicid = edx;
core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
sub_index = 1; sub_index = 1;
do { do {
cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx); cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
/* /*
* Check for the Core type in the implemented sub leaves. * Check for the Core type in the implemented sub leaves.
...@@ -83,23 +122,34 @@ int detect_extended_topology(struct cpuinfo_x86 *c) ...@@ -83,23 +122,34 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) { if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
core_level_siblings = LEVEL_MAX_SIBLINGS(ebx); core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
break; die_level_siblings = core_level_siblings;
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
}
if (LEAFB_SUBTYPE(ecx) == DIE_TYPE) {
die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
} }
sub_index++; sub_index++;
} while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE); } while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
die_select_mask = (~(-1 << die_plus_mask_width)) >>
c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width) core_plus_mask_width;
& core_select_mask;
c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width); c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid,
ht_mask_width) & core_select_mask;
c->cpu_die_id = apic->phys_pkg_id(c->initial_apicid,
core_plus_mask_width) & die_select_mask;
c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
die_plus_mask_width);
/* /*
* Reinit the apicid, now that we have extended initial_apicid. * Reinit the apicid, now that we have extended initial_apicid.
*/ */
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0); c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
c->x86_max_cores = (core_level_siblings / smp_num_siblings); c->x86_max_cores = (core_level_siblings / smp_num_siblings);
__max_die_per_package = (die_level_siblings / core_level_siblings);
#endif #endif
return 0; return 0;
} }
...@@ -89,6 +89,10 @@ EXPORT_PER_CPU_SYMBOL(cpu_sibling_map); ...@@ -89,6 +89,10 @@ EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map); DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_core_map);
EXPORT_PER_CPU_SYMBOL(cpu_core_map); EXPORT_PER_CPU_SYMBOL(cpu_core_map);
/* representing HT, core, and die siblings of each logical CPU */
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_die_map);
EXPORT_PER_CPU_SYMBOL(cpu_die_map);
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map); DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
/* Per CPU bogomips and other parameters */ /* Per CPU bogomips and other parameters */
...@@ -99,6 +103,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_info); ...@@ -99,6 +103,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_info);
unsigned int __max_logical_packages __read_mostly; unsigned int __max_logical_packages __read_mostly;
EXPORT_SYMBOL(__max_logical_packages); EXPORT_SYMBOL(__max_logical_packages);
static unsigned int logical_packages __read_mostly; static unsigned int logical_packages __read_mostly;
static unsigned int logical_die __read_mostly;
/* Maximum number of SMT threads on any online core */ /* Maximum number of SMT threads on any online core */
int __read_mostly __max_smt_threads = 1; int __read_mostly __max_smt_threads = 1;
...@@ -300,6 +305,26 @@ int topology_phys_to_logical_pkg(unsigned int phys_pkg) ...@@ -300,6 +305,26 @@ int topology_phys_to_logical_pkg(unsigned int phys_pkg)
return -1; return -1;
} }
EXPORT_SYMBOL(topology_phys_to_logical_pkg); EXPORT_SYMBOL(topology_phys_to_logical_pkg);
/**
* topology_phys_to_logical_die - Map a physical die id to logical
*
* Returns logical die id or -1 if not found
*/
int topology_phys_to_logical_die(unsigned int die_id, unsigned int cur_cpu)
{
int cpu;
int proc_id = cpu_data(cur_cpu).phys_proc_id;
for_each_possible_cpu(cpu) {
struct cpuinfo_x86 *c = &cpu_data(cpu);
if (c->initialized && c->cpu_die_id == die_id &&
c->phys_proc_id == proc_id)
return c->logical_die_id;
}
return -1;
}
EXPORT_SYMBOL(topology_phys_to_logical_die);
/** /**
* topology_update_package_map - Update the physical to logical package map * topology_update_package_map - Update the physical to logical package map
...@@ -324,6 +349,29 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu) ...@@ -324,6 +349,29 @@ int topology_update_package_map(unsigned int pkg, unsigned int cpu)
cpu_data(cpu).logical_proc_id = new; cpu_data(cpu).logical_proc_id = new;
return 0; return 0;
} }
/**
* topology_update_die_map - Update the physical to logical die map
* @die: The die id as retrieved via CPUID
* @cpu: The cpu for which this is updated
*/
int topology_update_die_map(unsigned int die, unsigned int cpu)
{
int new;
/* Already available somewhere? */
new = topology_phys_to_logical_die(die, cpu);
if (new >= 0)
goto found;
new = logical_die++;
if (new != die) {
pr_info("CPU %u Converting physical %u to logical die %u\n",
cpu, die, new);
}
found:
cpu_data(cpu).logical_die_id = new;
return 0;
}
void __init smp_store_boot_cpu_info(void) void __init smp_store_boot_cpu_info(void)
{ {
...@@ -333,6 +381,7 @@ void __init smp_store_boot_cpu_info(void) ...@@ -333,6 +381,7 @@ void __init smp_store_boot_cpu_info(void)
*c = boot_cpu_data; *c = boot_cpu_data;
c->cpu_index = id; c->cpu_index = id;
topology_update_package_map(c->phys_proc_id, id); topology_update_package_map(c->phys_proc_id, id);
topology_update_die_map(c->cpu_die_id, id);
c->initialized = true; c->initialized = true;
} }
...@@ -387,6 +436,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) ...@@ -387,6 +436,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
int cpu1 = c->cpu_index, cpu2 = o->cpu_index; int cpu1 = c->cpu_index, cpu2 = o->cpu_index;
if (c->phys_proc_id == o->phys_proc_id && if (c->phys_proc_id == o->phys_proc_id &&
c->cpu_die_id == o->cpu_die_id &&
per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) { per_cpu(cpu_llc_id, cpu1) == per_cpu(cpu_llc_id, cpu2)) {
if (c->cpu_core_id == o->cpu_core_id) if (c->cpu_core_id == o->cpu_core_id)
return topology_sane(c, o, "smt"); return topology_sane(c, o, "smt");
...@@ -398,6 +448,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) ...@@ -398,6 +448,7 @@ static bool match_smt(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
} }
} else if (c->phys_proc_id == o->phys_proc_id && } else if (c->phys_proc_id == o->phys_proc_id &&
c->cpu_die_id == o->cpu_die_id &&
c->cpu_core_id == o->cpu_core_id) { c->cpu_core_id == o->cpu_core_id) {
return topology_sane(c, o, "smt"); return topology_sane(c, o, "smt");
} }
...@@ -460,6 +511,15 @@ static bool match_pkg(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o) ...@@ -460,6 +511,15 @@ static bool match_pkg(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
return false; return false;
} }
static bool match_die(struct cpuinfo_x86 *c, struct cpuinfo_x86 *o)
{
if ((c->phys_proc_id == o->phys_proc_id) &&
(c->cpu_die_id == o->cpu_die_id))
return true;
return false;
}
#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC) #if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC)
static inline int x86_sched_itmt_flags(void) static inline int x86_sched_itmt_flags(void)
{ {
...@@ -522,6 +582,7 @@ void set_cpu_sibling_map(int cpu) ...@@ -522,6 +582,7 @@ void set_cpu_sibling_map(int cpu)
cpumask_set_cpu(cpu, topology_sibling_cpumask(cpu)); cpumask_set_cpu(cpu, topology_sibling_cpumask(cpu));
cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu)); cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
cpumask_set_cpu(cpu, topology_core_cpumask(cpu)); cpumask_set_cpu(cpu, topology_core_cpumask(cpu));
cpumask_set_cpu(cpu, topology_die_cpumask(cpu));
c->booted_cores = 1; c->booted_cores = 1;
return; return;
} }
...@@ -570,6 +631,9 @@ void set_cpu_sibling_map(int cpu) ...@@ -570,6 +631,9 @@ void set_cpu_sibling_map(int cpu)
} }
if (match_pkg(c, o) && !topology_same_node(c, o)) if (match_pkg(c, o) && !topology_same_node(c, o))
x86_has_numa_in_package = true; x86_has_numa_in_package = true;
if ((i == cpu) || (has_mp && match_die(c, o)))
link_mask(topology_die_cpumask, cpu, i);
} }
threads = cpumask_weight(topology_sibling_cpumask(cpu)); threads = cpumask_weight(topology_sibling_cpumask(cpu));
...@@ -1174,6 +1238,7 @@ static __init void disable_smp(void) ...@@ -1174,6 +1238,7 @@ static __init void disable_smp(void)
physid_set_mask_of_physid(0, &phys_cpu_present_map); physid_set_mask_of_physid(0, &phys_cpu_present_map);
cpumask_set_cpu(0, topology_sibling_cpumask(0)); cpumask_set_cpu(0, topology_sibling_cpumask(0));
cpumask_set_cpu(0, topology_core_cpumask(0)); cpumask_set_cpu(0, topology_core_cpumask(0));
cpumask_set_cpu(0, topology_die_cpumask(0));
} }
/* /*
...@@ -1269,6 +1334,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) ...@@ -1269,6 +1334,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
zalloc_cpumask_var(&per_cpu(cpu_die_map, i), GFP_KERNEL);
zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL); zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
} }
...@@ -1489,6 +1555,8 @@ static void remove_siblinginfo(int cpu) ...@@ -1489,6 +1555,8 @@ static void remove_siblinginfo(int cpu)
cpu_data(sibling).booted_cores--; cpu_data(sibling).booted_cores--;
} }
for_each_cpu(sibling, topology_die_cpumask(cpu))
cpumask_clear_cpu(cpu, topology_die_cpumask(sibling));
for_each_cpu(sibling, topology_sibling_cpumask(cpu)) for_each_cpu(sibling, topology_sibling_cpumask(cpu))
cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling)); cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) for_each_cpu(sibling, cpu_llc_shared_mask(cpu))
...@@ -1496,6 +1564,7 @@ static void remove_siblinginfo(int cpu) ...@@ -1496,6 +1564,7 @@ static void remove_siblinginfo(int cpu)
cpumask_clear(cpu_llc_shared_mask(cpu)); cpumask_clear(cpu_llc_shared_mask(cpu));
cpumask_clear(topology_sibling_cpumask(cpu)); cpumask_clear(topology_sibling_cpumask(cpu));
cpumask_clear(topology_core_cpumask(cpu)); cpumask_clear(topology_core_cpumask(cpu));
cpumask_clear(topology_die_cpumask(cpu));
c->cpu_core_id = 0; c->cpu_core_id = 0;
c->booted_cores = 0; c->booted_cores = 0;
cpumask_clear_cpu(cpu, cpu_sibling_setup_mask); cpumask_clear_cpu(cpu, cpu_sibling_setup_mask);
......
...@@ -251,6 +251,7 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus) ...@@ -251,6 +251,7 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus)
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL); zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL); zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
zalloc_cpumask_var(&per_cpu(cpu_die_map, i), GFP_KERNEL);
zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL); zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
} }
set_cpu_sibling_map(0); set_cpu_sibling_map(0);
......
...@@ -43,6 +43,9 @@ static ssize_t name##_list_show(struct device *dev, \ ...@@ -43,6 +43,9 @@ static ssize_t name##_list_show(struct device *dev, \
define_id_show_func(physical_package_id); define_id_show_func(physical_package_id);
static DEVICE_ATTR_RO(physical_package_id); static DEVICE_ATTR_RO(physical_package_id);
define_id_show_func(die_id);
static DEVICE_ATTR_RO(die_id);
define_id_show_func(core_id); define_id_show_func(core_id);
static DEVICE_ATTR_RO(core_id); static DEVICE_ATTR_RO(core_id);
...@@ -50,10 +53,22 @@ define_siblings_show_func(thread_siblings, sibling_cpumask); ...@@ -50,10 +53,22 @@ define_siblings_show_func(thread_siblings, sibling_cpumask);
static DEVICE_ATTR_RO(thread_siblings); static DEVICE_ATTR_RO(thread_siblings);
static DEVICE_ATTR_RO(thread_siblings_list); static DEVICE_ATTR_RO(thread_siblings_list);
define_siblings_show_func(core_cpus, sibling_cpumask);
static DEVICE_ATTR_RO(core_cpus);
static DEVICE_ATTR_RO(core_cpus_list);
define_siblings_show_func(core_siblings, core_cpumask); define_siblings_show_func(core_siblings, core_cpumask);
static DEVICE_ATTR_RO(core_siblings); static DEVICE_ATTR_RO(core_siblings);
static DEVICE_ATTR_RO(core_siblings_list); static DEVICE_ATTR_RO(core_siblings_list);
define_siblings_show_func(die_cpus, die_cpumask);
static DEVICE_ATTR_RO(die_cpus);
static DEVICE_ATTR_RO(die_cpus_list);
define_siblings_show_func(package_cpus, core_cpumask);
static DEVICE_ATTR_RO(package_cpus);
static DEVICE_ATTR_RO(package_cpus_list);
#ifdef CONFIG_SCHED_BOOK #ifdef CONFIG_SCHED_BOOK
define_id_show_func(book_id); define_id_show_func(book_id);
static DEVICE_ATTR_RO(book_id); static DEVICE_ATTR_RO(book_id);
...@@ -72,11 +87,18 @@ static DEVICE_ATTR_RO(drawer_siblings_list); ...@@ -72,11 +87,18 @@ static DEVICE_ATTR_RO(drawer_siblings_list);
static struct attribute *default_attrs[] = { static struct attribute *default_attrs[] = {
&dev_attr_physical_package_id.attr, &dev_attr_physical_package_id.attr,
&dev_attr_die_id.attr,
&dev_attr_core_id.attr, &dev_attr_core_id.attr,
&dev_attr_thread_siblings.attr, &dev_attr_thread_siblings.attr,
&dev_attr_thread_siblings_list.attr, &dev_attr_thread_siblings_list.attr,
&dev_attr_core_cpus.attr,
&dev_attr_core_cpus_list.attr,
&dev_attr_core_siblings.attr, &dev_attr_core_siblings.attr,
&dev_attr_core_siblings_list.attr, &dev_attr_core_siblings_list.attr,
&dev_attr_die_cpus.attr,
&dev_attr_die_cpus_list.attr,
&dev_attr_package_cpus.attr,
&dev_attr_package_cpus_list.attr,
#ifdef CONFIG_SCHED_BOOK #ifdef CONFIG_SCHED_BOOK
&dev_attr_book_id.attr, &dev_attr_book_id.attr,
&dev_attr_book_siblings.attr, &dev_attr_book_siblings.attr,
......
...@@ -96,10 +96,10 @@ struct platform_data { ...@@ -96,10 +96,10 @@ struct platform_data {
struct device_attribute name_attr; struct device_attribute name_attr;
}; };
/* Keep track of how many package pointers we allocated in init() */ /* Keep track of how many zone pointers we allocated in init() */
static int max_packages __read_mostly; static int max_zones __read_mostly;
/* Array of package pointers. Serialized by cpu hotplug lock */ /* Array of zone pointers. Serialized by cpu hotplug lock */
static struct platform_device **pkg_devices; static struct platform_device **zone_devices;
static ssize_t show_label(struct device *dev, static ssize_t show_label(struct device *dev,
struct device_attribute *devattr, char *buf) struct device_attribute *devattr, char *buf)
...@@ -422,10 +422,10 @@ static int chk_ucode_version(unsigned int cpu) ...@@ -422,10 +422,10 @@ static int chk_ucode_version(unsigned int cpu)
static struct platform_device *coretemp_get_pdev(unsigned int cpu) static struct platform_device *coretemp_get_pdev(unsigned int cpu)
{ {
int pkgid = topology_logical_package_id(cpu); int id = topology_logical_die_id(cpu);
if (pkgid >= 0 && pkgid < max_packages) if (id >= 0 && id < max_zones)
return pkg_devices[pkgid]; return zone_devices[id];
return NULL; return NULL;
} }
...@@ -531,7 +531,7 @@ static int coretemp_probe(struct platform_device *pdev) ...@@ -531,7 +531,7 @@ static int coretemp_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct platform_data *pdata; struct platform_data *pdata;
/* Initialize the per-package data structures */ /* Initialize the per-zone data structures */
pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL); pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL);
if (!pdata) if (!pdata)
return -ENOMEM; return -ENOMEM;
...@@ -566,13 +566,13 @@ static struct platform_driver coretemp_driver = { ...@@ -566,13 +566,13 @@ static struct platform_driver coretemp_driver = {
static struct platform_device *coretemp_device_add(unsigned int cpu) static struct platform_device *coretemp_device_add(unsigned int cpu)
{ {
int err, pkgid = topology_logical_package_id(cpu); int err, zoneid = topology_logical_die_id(cpu);
struct platform_device *pdev; struct platform_device *pdev;
if (pkgid < 0) if (zoneid < 0)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
pdev = platform_device_alloc(DRVNAME, pkgid); pdev = platform_device_alloc(DRVNAME, zoneid);
if (!pdev) if (!pdev)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
...@@ -582,7 +582,7 @@ static struct platform_device *coretemp_device_add(unsigned int cpu) ...@@ -582,7 +582,7 @@ static struct platform_device *coretemp_device_add(unsigned int cpu)
return ERR_PTR(err); return ERR_PTR(err);
} }
pkg_devices[pkgid] = pdev; zone_devices[zoneid] = pdev;
return pdev; return pdev;
} }
...@@ -690,7 +690,7 @@ static int coretemp_cpu_offline(unsigned int cpu) ...@@ -690,7 +690,7 @@ static int coretemp_cpu_offline(unsigned int cpu)
* the rest. * the rest.
*/ */
if (cpumask_empty(&pd->cpumask)) { if (cpumask_empty(&pd->cpumask)) {
pkg_devices[topology_logical_package_id(cpu)] = NULL; zone_devices[topology_logical_die_id(cpu)] = NULL;
platform_device_unregister(pdev); platform_device_unregister(pdev);
return 0; return 0;
} }
...@@ -728,10 +728,10 @@ static int __init coretemp_init(void) ...@@ -728,10 +728,10 @@ static int __init coretemp_init(void)
if (!x86_match_cpu(coretemp_ids)) if (!x86_match_cpu(coretemp_ids))
return -ENODEV; return -ENODEV;
max_packages = topology_max_packages(); max_zones = topology_max_packages() * topology_max_die_per_package();
pkg_devices = kcalloc(max_packages, sizeof(struct platform_device *), zone_devices = kcalloc(max_zones, sizeof(struct platform_device *),
GFP_KERNEL); GFP_KERNEL);
if (!pkg_devices) if (!zone_devices)
return -ENOMEM; return -ENOMEM;
err = platform_driver_register(&coretemp_driver); err = platform_driver_register(&coretemp_driver);
...@@ -747,7 +747,7 @@ static int __init coretemp_init(void) ...@@ -747,7 +747,7 @@ static int __init coretemp_init(void)
outdrv: outdrv:
platform_driver_unregister(&coretemp_driver); platform_driver_unregister(&coretemp_driver);
kfree(pkg_devices); kfree(zone_devices);
return err; return err;
} }
module_init(coretemp_init) module_init(coretemp_init)
...@@ -756,7 +756,7 @@ static void __exit coretemp_exit(void) ...@@ -756,7 +756,7 @@ static void __exit coretemp_exit(void)
{ {
cpuhp_remove_state(coretemp_hp_online); cpuhp_remove_state(coretemp_hp_online);
platform_driver_unregister(&coretemp_driver); platform_driver_unregister(&coretemp_driver);
kfree(pkg_devices); kfree(zone_devices);
} }
module_exit(coretemp_exit) module_exit(coretemp_exit)
......
...@@ -178,12 +178,15 @@ struct rapl_domain { ...@@ -178,12 +178,15 @@ struct rapl_domain {
#define power_zone_to_rapl_domain(_zone) \ #define power_zone_to_rapl_domain(_zone) \
container_of(_zone, struct rapl_domain, power_zone) container_of(_zone, struct rapl_domain, power_zone)
/* maximum rapl package domain name: package-%d-die-%d */
#define PACKAGE_DOMAIN_NAME_LENGTH 30
/* Each physical package contains multiple domains, these are the common
/* Each rapl package contains multiple domains, these are the common
* data across RAPL domains within a package. * data across RAPL domains within a package.
*/ */
struct rapl_package { struct rapl_package {
unsigned int id; /* physical package/socket id */ unsigned int id; /* logical die id, equals physical 1-die systems */
unsigned int nr_domains; unsigned int nr_domains;
unsigned long domain_map; /* bit map of active domains */ unsigned long domain_map; /* bit map of active domains */
unsigned int power_unit; unsigned int power_unit;
...@@ -198,6 +201,7 @@ struct rapl_package { ...@@ -198,6 +201,7 @@ struct rapl_package {
int lead_cpu; /* one active cpu per package for access */ int lead_cpu; /* one active cpu per package for access */
/* Track active cpus */ /* Track active cpus */
struct cpumask cpumask; struct cpumask cpumask;
char name[PACKAGE_DOMAIN_NAME_LENGTH];
}; };
struct rapl_defaults { struct rapl_defaults {
...@@ -264,8 +268,9 @@ static struct powercap_control_type *control_type; /* PowerCap Controller */ ...@@ -264,8 +268,9 @@ static struct powercap_control_type *control_type; /* PowerCap Controller */
static struct rapl_domain *platform_rapl_domain; /* Platform (PSys) domain */ static struct rapl_domain *platform_rapl_domain; /* Platform (PSys) domain */
/* caller to ensure CPU hotplug lock is held */ /* caller to ensure CPU hotplug lock is held */
static struct rapl_package *find_package_by_id(int id) static struct rapl_package *rapl_find_package_domain(int cpu)
{ {
int id = topology_logical_die_id(cpu);
struct rapl_package *rp; struct rapl_package *rp;
list_for_each_entry(rp, &rapl_packages, plist) { list_for_each_entry(rp, &rapl_packages, plist) {
...@@ -925,8 +930,8 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu) ...@@ -925,8 +930,8 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
rp->time_unit = 1000000 / (1 << value); rp->time_unit = 1000000 / (1 << value);
pr_debug("Core CPU package %d energy=%dpJ, time=%dus, power=%duW\n", pr_debug("Core CPU %s energy=%dpJ, time=%dus, power=%duW\n",
rp->id, rp->energy_unit, rp->time_unit, rp->power_unit); rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
return 0; return 0;
} }
...@@ -950,8 +955,8 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu) ...@@ -950,8 +955,8 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET; value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
rp->time_unit = 1000000 / (1 << value); rp->time_unit = 1000000 / (1 << value);
pr_debug("Atom package %d energy=%dpJ, time=%dus, power=%duW\n", pr_debug("Atom %s energy=%dpJ, time=%dus, power=%duW\n",
rp->id, rp->energy_unit, rp->time_unit, rp->power_unit); rp->name, rp->energy_unit, rp->time_unit, rp->power_unit);
return 0; return 0;
} }
...@@ -1180,7 +1185,7 @@ static void rapl_update_domain_data(struct rapl_package *rp) ...@@ -1180,7 +1185,7 @@ static void rapl_update_domain_data(struct rapl_package *rp)
u64 val; u64 val;
for (dmn = 0; dmn < rp->nr_domains; dmn++) { for (dmn = 0; dmn < rp->nr_domains; dmn++) {
pr_debug("update package %d domain %s data\n", rp->id, pr_debug("update %s domain %s data\n", rp->name,
rp->domains[dmn].name); rp->domains[dmn].name);
/* exclude non-raw primitives */ /* exclude non-raw primitives */
for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) { for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++) {
...@@ -1205,7 +1210,6 @@ static void rapl_unregister_powercap(void) ...@@ -1205,7 +1210,6 @@ static void rapl_unregister_powercap(void)
static int rapl_package_register_powercap(struct rapl_package *rp) static int rapl_package_register_powercap(struct rapl_package *rp)
{ {
struct rapl_domain *rd; struct rapl_domain *rd;
char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/
struct powercap_zone *power_zone = NULL; struct powercap_zone *power_zone = NULL;
int nr_pl, ret; int nr_pl, ret;
...@@ -1216,20 +1220,16 @@ static int rapl_package_register_powercap(struct rapl_package *rp) ...@@ -1216,20 +1220,16 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
if (rd->id == RAPL_DOMAIN_PACKAGE) { if (rd->id == RAPL_DOMAIN_PACKAGE) {
nr_pl = find_nr_power_limit(rd); nr_pl = find_nr_power_limit(rd);
pr_debug("register socket %d package domain %s\n", pr_debug("register package domain %s\n", rp->name);
rp->id, rd->name);
memset(dev_name, 0, sizeof(dev_name));
snprintf(dev_name, sizeof(dev_name), "%s-%d",
rd->name, rp->id);
power_zone = powercap_register_zone(&rd->power_zone, power_zone = powercap_register_zone(&rd->power_zone,
control_type, control_type,
dev_name, NULL, rp->name, NULL,
&zone_ops[rd->id], &zone_ops[rd->id],
nr_pl, nr_pl,
&constraint_ops); &constraint_ops);
if (IS_ERR(power_zone)) { if (IS_ERR(power_zone)) {
pr_debug("failed to register package, %d\n", pr_debug("failed to register power zone %s\n",
rp->id); rp->name);
return PTR_ERR(power_zone); return PTR_ERR(power_zone);
} }
/* track parent zone in per package/socket data */ /* track parent zone in per package/socket data */
...@@ -1255,8 +1255,8 @@ static int rapl_package_register_powercap(struct rapl_package *rp) ...@@ -1255,8 +1255,8 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
&constraint_ops); &constraint_ops);
if (IS_ERR(power_zone)) { if (IS_ERR(power_zone)) {
pr_debug("failed to register power_zone, %d:%s:%s\n", pr_debug("failed to register power_zone, %s:%s\n",
rp->id, rd->name, dev_name); rp->name, rd->name);
ret = PTR_ERR(power_zone); ret = PTR_ERR(power_zone);
goto err_cleanup; goto err_cleanup;
} }
...@@ -1269,7 +1269,7 @@ static int rapl_package_register_powercap(struct rapl_package *rp) ...@@ -1269,7 +1269,7 @@ static int rapl_package_register_powercap(struct rapl_package *rp)
* failed after the first domain setup. * failed after the first domain setup.
*/ */
while (--rd >= rp->domains) { while (--rd >= rp->domains) {
pr_debug("unregister package %d domain %s\n", rp->id, rd->name); pr_debug("unregister %s domain %s\n", rp->name, rd->name);
powercap_unregister_zone(control_type, &rd->power_zone); powercap_unregister_zone(control_type, &rd->power_zone);
} }
...@@ -1300,7 +1300,7 @@ static int __init rapl_register_psys(void) ...@@ -1300,7 +1300,7 @@ static int __init rapl_register_psys(void)
rd->rpl[0].name = pl1_name; rd->rpl[0].name = pl1_name;
rd->rpl[1].prim_id = PL2_ENABLE; rd->rpl[1].prim_id = PL2_ENABLE;
rd->rpl[1].name = pl2_name; rd->rpl[1].name = pl2_name;
rd->rp = find_package_by_id(0); rd->rp = rapl_find_package_domain(0);
power_zone = powercap_register_zone(&rd->power_zone, control_type, power_zone = powercap_register_zone(&rd->power_zone, control_type,
"psys", NULL, "psys", NULL,
...@@ -1379,8 +1379,8 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd) ...@@ -1379,8 +1379,8 @@ static void rapl_detect_powerlimit(struct rapl_domain *rd)
/* check if the domain is locked by BIOS, ignore if MSR doesn't exist */ /* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) { if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
if (val64) { if (val64) {
pr_info("RAPL package %d domain %s locked by BIOS\n", pr_info("RAPL %s domain %s locked by BIOS\n",
rd->rp->id, rd->name); rd->rp->name, rd->name);
rd->state |= DOMAIN_STATE_BIOS_LOCKED; rd->state |= DOMAIN_STATE_BIOS_LOCKED;
} }
} }
...@@ -1409,10 +1409,10 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu) ...@@ -1409,10 +1409,10 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
} }
rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX); rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
if (!rp->nr_domains) { if (!rp->nr_domains) {
pr_debug("no valid rapl domains found in package %d\n", rp->id); pr_debug("no valid rapl domains found in %s\n", rp->name);
return -ENODEV; return -ENODEV;
} }
pr_debug("found %d domains on package %d\n", rp->nr_domains, rp->id); pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name);
rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain), rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain),
GFP_KERNEL); GFP_KERNEL);
...@@ -1445,8 +1445,8 @@ static void rapl_remove_package(struct rapl_package *rp) ...@@ -1445,8 +1445,8 @@ static void rapl_remove_package(struct rapl_package *rp)
rd_package = rd; rd_package = rd;
continue; continue;
} }
pr_debug("remove package, undo power limit on %d: %s\n", pr_debug("remove package, undo power limit on %s: %s\n",
rp->id, rd->name); rp->name, rd->name);
powercap_unregister_zone(control_type, &rd->power_zone); powercap_unregister_zone(control_type, &rd->power_zone);
} }
/* do parent zone last */ /* do parent zone last */
...@@ -1456,9 +1456,11 @@ static void rapl_remove_package(struct rapl_package *rp) ...@@ -1456,9 +1456,11 @@ static void rapl_remove_package(struct rapl_package *rp)
} }
/* called from CPU hotplug notifier, hotplug lock held */ /* called from CPU hotplug notifier, hotplug lock held */
static struct rapl_package *rapl_add_package(int cpu, int pkgid) static struct rapl_package *rapl_add_package(int cpu)
{ {
int id = topology_logical_die_id(cpu);
struct rapl_package *rp; struct rapl_package *rp;
struct cpuinfo_x86 *c = &cpu_data(cpu);
int ret; int ret;
rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL); rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
...@@ -1466,9 +1468,16 @@ static struct rapl_package *rapl_add_package(int cpu, int pkgid) ...@@ -1466,9 +1468,16 @@ static struct rapl_package *rapl_add_package(int cpu, int pkgid)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
/* add the new package to the list */ /* add the new package to the list */
rp->id = pkgid; rp->id = id;
rp->lead_cpu = cpu; rp->lead_cpu = cpu;
if (topology_max_die_per_package() > 1)
snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH,
"package-%d-die-%d", c->phys_proc_id, c->cpu_die_id);
else
snprintf(rp->name, PACKAGE_DOMAIN_NAME_LENGTH, "package-%d",
c->phys_proc_id);
/* check if the package contains valid domains */ /* check if the package contains valid domains */
if (rapl_detect_domains(rp, cpu) || if (rapl_detect_domains(rp, cpu) ||
rapl_defaults->check_unit(rp, cpu)) { rapl_defaults->check_unit(rp, cpu)) {
...@@ -1497,12 +1506,11 @@ static struct rapl_package *rapl_add_package(int cpu, int pkgid) ...@@ -1497,12 +1506,11 @@ static struct rapl_package *rapl_add_package(int cpu, int pkgid)
*/ */
static int rapl_cpu_online(unsigned int cpu) static int rapl_cpu_online(unsigned int cpu)
{ {
int pkgid = topology_physical_package_id(cpu);
struct rapl_package *rp; struct rapl_package *rp;
rp = find_package_by_id(pkgid); rp = rapl_find_package_domain(cpu);
if (!rp) { if (!rp) {
rp = rapl_add_package(cpu, pkgid); rp = rapl_add_package(cpu);
if (IS_ERR(rp)) if (IS_ERR(rp))
return PTR_ERR(rp); return PTR_ERR(rp);
} }
...@@ -1512,11 +1520,10 @@ static int rapl_cpu_online(unsigned int cpu) ...@@ -1512,11 +1520,10 @@ static int rapl_cpu_online(unsigned int cpu)
static int rapl_cpu_down_prep(unsigned int cpu) static int rapl_cpu_down_prep(unsigned int cpu)
{ {
int pkgid = topology_physical_package_id(cpu);
struct rapl_package *rp; struct rapl_package *rp;
int lead_cpu; int lead_cpu;
rp = find_package_by_id(pkgid); rp = rapl_find_package_domain(cpu);
if (!rp) if (!rp)
return 0; return 0;
......
...@@ -184,6 +184,9 @@ static inline int cpu_to_mem(int cpu) ...@@ -184,6 +184,9 @@ static inline int cpu_to_mem(int cpu)
#ifndef topology_physical_package_id #ifndef topology_physical_package_id
#define topology_physical_package_id(cpu) ((void)(cpu), -1) #define topology_physical_package_id(cpu) ((void)(cpu), -1)
#endif #endif
#ifndef topology_die_id
#define topology_die_id(cpu) ((void)(cpu), -1)
#endif
#ifndef topology_core_id #ifndef topology_core_id
#define topology_core_id(cpu) ((void)(cpu), 0) #define topology_core_id(cpu) ((void)(cpu), 0)
#endif #endif
...@@ -193,6 +196,9 @@ static inline int cpu_to_mem(int cpu) ...@@ -193,6 +196,9 @@ static inline int cpu_to_mem(int cpu)
#ifndef topology_core_cpumask #ifndef topology_core_cpumask
#define topology_core_cpumask(cpu) cpumask_of(cpu) #define topology_core_cpumask(cpu) cpumask_of(cpu)
#endif #endif
#ifndef topology_die_cpumask
#define topology_die_cpumask(cpu) cpumask_of(cpu)
#endif
#ifdef CONFIG_SCHED_SMT #ifdef CONFIG_SCHED_SMT
static inline const struct cpumask *cpu_smt_mask(int cpu) static inline const struct cpumask *cpu_smt_mask(int cpu)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment