linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR
@ 2022-11-17 12:28 alexander.antonov
  2022-11-17 12:28 ` [PATCH 01/11] perf/x86/intel/uncore: Generalize IIO topology support alexander.antonov
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Starting with the Intel Xeon Scalable family, Intel processors use a
coherent interconnect for scaling to multiple sockets, known as Intel
Ultra Path Interconnect (Intel UPI). The Intel UPI technology provides
a cache-coherent socket-to-socket external communication interface between
processors.

Unfortunately, users have little idea on how sockets are connected to
each other. This patchset extends the current mapping implementation by
adding sysfs attributes for UPI PMON blocks in the same manner as was
done for IIO blocks. These attributes reveal the topology of the system
by showing which how sockets and UPI controllers are connected to each
other.

Example for a 4-socket Sapphire Rapids server:

# tail /sys/devices/uncore_upi_*/die*
==> /sys/devices/uncore_upi_0/die0 <==
upi_1,die_1

==> /sys/devices/uncore_upi_0/die1 <==
upi_0,die_3

==> /sys/devices/uncore_upi_0/die2 <==
upi_1,die_3

==> /sys/devices/uncore_upi_0/die3 <==
upi_0,die_1

==> /sys/devices/uncore_upi_1/die0 <==
upi_1,die_2

==> /sys/devices/uncore_upi_1/die1 <==
upi_0,die_0

==> /sys/devices/uncore_upi_1/die2 <==
upi_1,die_0

==> /sys/devices/uncore_upi_1/die3 <==
upi_0,die_2

==> /sys/devices/uncore_upi_2/die0 <==
upi_2,die_3

==> /sys/devices/uncore_upi_2/die1 <==
upi_2,die_2

==> /sys/devices/uncore_upi_2/die2 <==
upi_2,die_1

==> /sys/devices/uncore_upi_2/die3 <==
upi_2,die_0

The following output:
# cat /sys/devices/uncore_upi_X/dieY
upi_Z,die_W
means that UPI link number X on die Y is connected to UPI link Z on die W.

Changes are splitted into two separate parts:
1. kernel part - adds and fills new sysfs attributes for UPI PMON blocks
2. perf-tool part - enables UPI topology info and per-link UPI metrics for
'perf iostat' mode. See example below.

The 'perf iostat list' will be extend to show IIO and UPI mappings, for example:

# perf iostat list
S0-uncore_iio_0<0000:00>
S1-uncore_iio_0<0000:80>
S0-uncore_iio_1<0000:17>
S1-uncore_iio_1<0000:85>
S0-uncore_iio_2<0000:3a>
S1-uncore_iio_2<0000:ae>
S0-uncore_iio_3<0000:5d>
S1-uncore_iio_3<0000:d7>
UPI Link 0 on Socket 0 -> UPI Link 1 on Socket 1
UPI Link 0 on Socket 1 -> UPI Link 1 on Socket 0
UPI Link 1 on Socket 0 -> UPI Link 0 on Socket 1
UPI Link 1 on Socket 1 -> UPI Link 0 on Socket 0

The 'perf iostat upi' mode will be added to show per-link UPI metrics:
# perf iostat upi
                                            link            Outgoing Data(GB)      Outgoing Non-Data(GB)
UPI Link 0 on Socket 0 -> UPI Link 1 on Socket 1                    0                      0
UPI Link 0 on Socket 1 -> UPI Link 1 on Socket 0                    0                      0
UPI Link 1 on Socket 0 -> UPI Link 0 on Socket 1                    0                      0
UPI Link 1 on Socket 1 -> UPI Link 0 on Socket 0                    0                      0

       1.437023089 seconds time elapsed

Alexander Antonov (11):
  perf/x86/intel/uncore: Generalize IIO topology support
  perf/x86/intel/uncore: Introduce UPI topology type
  perf/x86/intel/uncore: Clear attr_update properly
  perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D
  perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs
  perf/x86/intel/uncore: Enable UPI topology discovery for Skylake
    Server
  perf/x86/intel/uncore: Get UPI NodeID and GroupID
  perf/x86/intel/uncore: Enable UPI topology discovery for Icelake
    Server
  perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire
    Rapids
  perf/x86/intel/uncore: Update sysfs-devices-mapping file
  perf/x86/intel/uncore: Make set_mapping() procedure void

 .../ABI/testing/sysfs-devices-mapping         |  30 +-
 arch/x86/events/intel/uncore.h                |  24 +-
 arch/x86/events/intel/uncore_snbep.c          | 492 +++++++++++++++---
 3 files changed, 480 insertions(+), 66 deletions(-)


base-commit: ee6050c8af96bba2f81e8b0793a1fc2f998fcd20
-- 
2.25.1


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH 01/11] perf/x86/intel/uncore: Generalize IIO topology support
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:03   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 02/11] perf/x86/intel/uncore: Introduce UPI topology type alexander.antonov
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Current implementation of uncore mapping doesn't support different types
of uncore PMUs which have its own topology context. This patch generalizes
Intel uncore topology implementation to be able easily introduce support
for new uncore blocks.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore.h       |  14 ++-
 arch/x86/events/intel/uncore_snbep.c | 152 +++++++++++++++++++--------
 2 files changed, 122 insertions(+), 44 deletions(-)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 2adeaf4de4df..917cff1e7815 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -88,7 +88,7 @@ struct intel_uncore_type {
 	 * to identify which platform component each PMON block of that type is
 	 * supposed to monitor.
 	 */
-	struct intel_uncore_topology *topology;
+	struct intel_uncore_topology **topology;
 	/*
 	 * Optional callbacks for managing mapping of Uncore units to PMONs
 	 */
@@ -178,11 +178,19 @@ struct freerunning_counters {
 	unsigned *box_offsets;
 };
 
-struct intel_uncore_topology {
-	u64 configuration;
+struct uncore_iio_topology {
+	int pci_bus_no;
 	int segment;
 };
 
+struct intel_uncore_topology {
+	int pmu_idx;
+	union {
+		void *untyped;
+		struct uncore_iio_topology *iio;
+	};
+};
+
 struct pci2phy_map {
 	struct list_head list;
 	int segment;
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index ed869443efb2..469ff889ea08 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3699,10 +3699,16 @@ static struct intel_uncore_ops skx_uncore_iio_ops = {
 	.read_counter		= uncore_msr_read_counter,
 };
 
-static inline u8 skx_iio_stack(struct intel_uncore_pmu *pmu, int die)
+static struct intel_uncore_topology *pmu_topology(struct intel_uncore_pmu *pmu, int die)
 {
-	return pmu->type->topology[die].configuration >>
-	       (pmu->pmu_idx * BUS_NUM_STRIDE);
+	int idx;
+
+	for (idx = 0; idx < pmu->type->num_boxes; idx++) {
+		if (pmu->type->topology[die][idx].pmu_idx == pmu->pmu_idx)
+			return &pmu->type->topology[die][idx];
+	}
+
+	return NULL;
 }
 
 static umode_t
@@ -3710,8 +3716,9 @@ pmu_iio_mapping_visible(struct kobject *kobj, struct attribute *attr,
 			 int die, int zero_bus_pmu)
 {
 	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
+	struct intel_uncore_topology *pmut = pmu_topology(pmu, die);
 
-	return (!skx_iio_stack(pmu, die) && pmu->pmu_idx != zero_bus_pmu) ? 0 : attr->mode;
+	return (pmut && !pmut->iio->pci_bus_no && pmu->pmu_idx != zero_bus_pmu) ? 0 : attr->mode;
 }
 
 static umode_t
@@ -3727,9 +3734,10 @@ static ssize_t skx_iio_mapping_show(struct device *dev,
 	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
 	struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
 	long die = (long)ea->var;
+	struct intel_uncore_topology *pmut = pmu_topology(pmu, die);
 
-	return sprintf(buf, "%04x:%02x\n", pmu->type->topology[die].segment,
-					   skx_iio_stack(pmu, die));
+	return sprintf(buf, "%04x:%02x\n", pmut ? pmut->iio->segment : 0,
+					   pmut ? pmut->iio->pci_bus_no : 0);
 }
 
 static int skx_msr_cpu_bus_read(int cpu, u64 *topology)
@@ -3764,18 +3772,77 @@ static int die_to_cpu(int die)
 	return res;
 }
 
+enum {
+	IIO_TOPOLOGY_TYPE,
+	TOPOLOGY_MAX
+};
+
+static const size_t topology_size[TOPOLOGY_MAX] = {
+	sizeof(*((struct intel_uncore_topology *)NULL)->iio)
+};
+
+static int pmu_alloc_topology(struct intel_uncore_type *type, int topology_type)
+{
+	int die, idx;
+	struct intel_uncore_topology **topology;
+
+	if (!type->num_boxes)
+		return -EPERM;
+
+	topology = kcalloc(uncore_max_dies(), sizeof(*topology), GFP_KERNEL);
+	if (!topology)
+		goto err;
+
+	for (die = 0; die < uncore_max_dies(); die++) {
+		topology[die] = kcalloc(type->num_boxes, sizeof(**topology), GFP_KERNEL);
+		if (!topology[die])
+			goto clear;
+		for (idx = 0; idx < type->num_boxes; idx++) {
+			topology[die][idx].untyped = kcalloc(type->num_boxes,
+							     topology_size[topology_type],
+							     GFP_KERNEL);
+			if (!topology[die][idx].untyped)
+				goto clear;
+		}
+	}
+
+	type->topology = topology;
+
+	return 0;
+clear:
+	for (; die >= 0; die--) {
+		for (idx = 0; idx < type->num_boxes; idx++)
+			kfree(topology[die][idx].untyped);
+		kfree(topology[die]);
+	}
+	kfree(topology);
+err:
+	return -ENOMEM;
+}
+
+static void pmu_free_topology(struct intel_uncore_type *type)
+{
+	int die, idx;
+
+	if (type->topology) {
+		for (die = 0; die < uncore_max_dies(); die++) {
+			for (idx = 0; idx < type->num_boxes; idx++)
+				kfree(type->topology[die][idx].untyped);
+			kfree(type->topology[die]);
+		}
+		kfree(type->topology);
+		type->topology = NULL;
+	}
+}
+
 static int skx_iio_get_topology(struct intel_uncore_type *type)
 {
 	int die, ret = -EPERM;
-
-	type->topology = kcalloc(uncore_max_dies(), sizeof(*type->topology),
-				 GFP_KERNEL);
-	if (!type->topology)
-		return -ENOMEM;
+	u64 configuration;
+	int idx;
 
 	for (die = 0; die < uncore_max_dies(); die++) {
-		ret = skx_msr_cpu_bus_read(die_to_cpu(die),
-					   &type->topology[die].configuration);
+		ret = skx_msr_cpu_bus_read(die_to_cpu(die), &configuration);
 		if (ret)
 			break;
 
@@ -3783,12 +3850,12 @@ static int skx_iio_get_topology(struct intel_uncore_type *type)
 		if (ret < 0)
 			break;
 
-		type->topology[die].segment = ret;
-	}
-
-	if (ret < 0) {
-		kfree(type->topology);
-		type->topology = NULL;
+		for (idx = 0; idx < type->num_boxes; idx++) {
+			type->topology[die][idx].pmu_idx = idx;
+			type->topology[die][idx].iio->segment = ret;
+			type->topology[die][idx].iio->pci_bus_no =
+				(configuration >> (idx * BUS_NUM_STRIDE)) & 0xff;
+		}
 	}
 
 	return ret;
@@ -3804,7 +3871,9 @@ static const struct attribute_group *skx_iio_attr_update[] = {
 };
 
 static int
-pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
+		ssize_t (*show)(struct device*, struct device_attribute*, char*),
+		int topology_type)
 {
 	char buf[64];
 	int ret;
@@ -3812,10 +3881,14 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 	struct attribute **attrs = NULL;
 	struct dev_ext_attribute *eas = NULL;
 
-	ret = type->get_topology(type);
+	ret = pmu_alloc_topology(type, topology_type);
 	if (ret < 0)
 		goto clear_attr_update;
 
+	ret = type->get_topology(type);
+	if (ret < 0)
+		goto clear_topology;
+
 	ret = -ENOMEM;
 
 	/* One more for NULL. */
@@ -3828,13 +3901,13 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 		goto clear_attrs;
 
 	for (die = 0; die < uncore_max_dies(); die++) {
-		sprintf(buf, "die%ld", die);
+		snprintf(buf, sizeof(buf), "die%ld", die);
 		sysfs_attr_init(&eas[die].attr.attr);
 		eas[die].attr.attr.name = kstrdup(buf, GFP_KERNEL);
 		if (!eas[die].attr.attr.name)
 			goto err;
 		eas[die].attr.attr.mode = 0444;
-		eas[die].attr.show = skx_iio_mapping_show;
+		eas[die].attr.show = show;
 		eas[die].attr.store = NULL;
 		eas[die].var = (void *)die;
 		attrs[die] = &eas[die].attr.attr;
@@ -3849,14 +3922,14 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 clear_attrs:
 	kfree(attrs);
 clear_topology:
-	kfree(type->topology);
+	pmu_free_topology(type);
 clear_attr_update:
 	type->attr_update = NULL;
 	return ret;
 }
 
 static void
-pmu_iio_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+pmu_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 {
 	struct attribute **attr = ag->attrs;
 
@@ -3868,7 +3941,13 @@ pmu_iio_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *
 	kfree(attr_to_ext_attr(*ag->attrs));
 	kfree(ag->attrs);
 	ag->attrs = NULL;
-	kfree(type->topology);
+	pmu_free_topology(type);
+}
+
+static int
+pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+{
+	return pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
 }
 
 static int skx_iio_set_mapping(struct intel_uncore_type *type)
@@ -3878,7 +3957,7 @@ static int skx_iio_set_mapping(struct intel_uncore_type *type)
 
 static void skx_iio_cleanup_mapping(struct intel_uncore_type *type)
 {
-	pmu_iio_cleanup_mapping(type, &skx_iio_mapping_group);
+	pmu_cleanup_mapping(type, &skx_iio_mapping_group);
 }
 
 static struct intel_uncore_type skx_uncore_iio = {
@@ -4461,11 +4540,6 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map
 	int die, stack_id, ret = -EPERM;
 	struct pci_dev *dev = NULL;
 
-	type->topology = kcalloc(uncore_max_dies(), sizeof(*type->topology),
-				 GFP_KERNEL);
-	if (!type->topology)
-		return -ENOMEM;
-
 	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, SNR_ICX_MESH2IIO_MMAP_DID, dev))) {
 		ret = pci_read_config_dword(dev, SNR_ICX_SAD_CONTROL_CFG, &sad_cfg);
 		if (ret) {
@@ -4483,13 +4557,9 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map
 		/* Convert stack id from SAD_CONTROL to PMON notation. */
 		stack_id = sad_pmon_mapping[stack_id];
 
-		((u8 *)&(type->topology[die].configuration))[stack_id] = dev->bus->number;
-		type->topology[die].segment = pci_domain_nr(dev->bus);
-	}
-
-	if (ret) {
-		kfree(type->topology);
-		type->topology = NULL;
+		type->topology[die][stack_id].iio->segment = pci_domain_nr(dev->bus);
+		type->topology[die][stack_id].pmu_idx = stack_id;
+		type->topology[die][stack_id].iio->pci_bus_no = dev->bus->number;
 	}
 
 	return ret;
@@ -4526,7 +4596,7 @@ static int snr_iio_set_mapping(struct intel_uncore_type *type)
 
 static void snr_iio_cleanup_mapping(struct intel_uncore_type *type)
 {
-	pmu_iio_cleanup_mapping(type, &snr_iio_mapping_group);
+	pmu_cleanup_mapping(type, &snr_iio_mapping_group);
 }
 
 static struct event_constraint snr_uncore_iio_constraints[] = {
@@ -5144,7 +5214,7 @@ static int icx_iio_set_mapping(struct intel_uncore_type *type)
 
 static void icx_iio_cleanup_mapping(struct intel_uncore_type *type)
 {
-	pmu_iio_cleanup_mapping(type, &icx_iio_mapping_group);
+	pmu_cleanup_mapping(type, &icx_iio_mapping_group);
 }
 
 static struct intel_uncore_type icx_uncore_iio = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 02/11] perf/x86/intel/uncore: Introduce UPI topology type
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
  2022-11-17 12:28 ` [PATCH 01/11] perf/x86/intel/uncore: Generalize IIO topology support alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:03   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 03/11] perf/x86/intel/uncore: Clear attr_update properly alexander.antonov
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

This patch introduces new 'uncore_upi_topology' topology type to support
UPI topology discovery.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore.h       | 7 +++++++
 arch/x86/events/intel/uncore_snbep.c | 4 +++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 917cff1e7815..ef1414957623 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -183,11 +183,18 @@ struct uncore_iio_topology {
 	int segment;
 };
 
+struct uncore_upi_topology {
+	int die_to;
+	int pmu_idx_to;
+	int enabled;
+};
+
 struct intel_uncore_topology {
 	int pmu_idx;
 	union {
 		void *untyped;
 		struct uncore_iio_topology *iio;
+		struct uncore_upi_topology *upi;
 	};
 };
 
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 469ff889ea08..d3323f13c304 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3774,11 +3774,13 @@ static int die_to_cpu(int die)
 
 enum {
 	IIO_TOPOLOGY_TYPE,
+	UPI_TOPOLOGY_TYPE,
 	TOPOLOGY_MAX
 };
 
 static const size_t topology_size[TOPOLOGY_MAX] = {
-	sizeof(*((struct intel_uncore_topology *)NULL)->iio)
+	sizeof(*((struct intel_uncore_topology *)NULL)->iio),
+	sizeof(*((struct intel_uncore_topology *)NULL)->upi)
 };
 
 static int pmu_alloc_topology(struct intel_uncore_type *type, int topology_type)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 03/11] perf/x86/intel/uncore: Clear attr_update properly
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
  2022-11-17 12:28 ` [PATCH 01/11] perf/x86/intel/uncore: Generalize IIO topology support alexander.antonov
  2022-11-17 12:28 ` [PATCH 02/11] perf/x86/intel/uncore: Introduce UPI topology type alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 04/11] perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D alexander.antonov
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Current clear_attr_update procedure in pmu_set_mapping() sets attr_update
field in NULL that is not correct because intel_uncore_type pmu types can
contain several groups in attr_update field. For example, SPR platform
already has uncore_alias_group to update and then UPI topology group will
be added in next patches.

Fix current behavior and clear attr_update group related to mapping only.

Fixes: bb42b3d39781 ("perf/x86/intel/uncore: Expose an Uncore unit to IIO PMON mapping")
Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Cc: stable@vger.kernel.org
---
 arch/x86/events/intel/uncore_snbep.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index d3323f13c304..0d06b56b8a33 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3872,6 +3872,21 @@ static const struct attribute_group *skx_iio_attr_update[] = {
 	NULL,
 };
 
+static void pmu_clear_mapping_attr(const struct attribute_group **groups,
+				   struct attribute_group *ag)
+{
+	int i;
+
+	for (i = 0; groups[i]; i++) {
+		if (groups[i] == ag) {
+			for (i++; groups[i]; i++)
+				groups[i - 1] = groups[i];
+			groups[i - 1] = NULL;
+			break;
+		}
+	}
+}
+
 static int
 pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 		ssize_t (*show)(struct device*, struct device_attribute*, char*),
@@ -3926,7 +3941,7 @@ pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 clear_topology:
 	pmu_free_topology(type);
 clear_attr_update:
-	type->attr_update = NULL;
+	pmu_clear_mapping_attr(type->attr_update, ag);
 	return ret;
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 04/11] perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (2 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 03/11] perf/x86/intel/uncore: Clear attr_update properly alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 05/11] perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs alexander.antonov
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Current implementation of I/O stacks to PMU mapping doesn't support ICX-D.
Detect ICX-D system to disable mapping.

Fixes: 10337e95e04c ("perf/x86/intel/uncore: Enable I/O stacks to IIO PMON mapping on ICX")
Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Cc: stable@vger.kernel.org
---
 arch/x86/events/intel/uncore.h       | 1 +
 arch/x86/events/intel/uncore_snbep.c | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index ef1414957623..fac3612289f1 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -2,6 +2,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <asm/apicdef.h>
+#include <asm/intel-family.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 
 #include <linux/perf_event.h>
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 0d06b56b8a33..e14b96398377 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -5226,6 +5226,11 @@ static int icx_iio_get_topology(struct intel_uncore_type *type)
 
 static int icx_iio_set_mapping(struct intel_uncore_type *type)
 {
+	/* Detect ICX-D system. This case is not supported */
+	if (boot_cpu_data.x86_model == INTEL_FAM6_ICELAKE_D) {
+		pmu_clear_mapping_attr(type->attr_update, &icx_iio_mapping_group);
+		return -EPERM;
+	}
 	return pmu_iio_set_mapping(type, &icx_iio_mapping_group);
 }
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 05/11] perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (3 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 04/11] perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 06/11] perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server alexander.antonov
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Factor out a generic code from skx_iio_get_topology() to skx_pmu_get_topology()
to avoid code duplication. This code will be used by get_topology() procedure
for SKX UPI PMUs in the further patch.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore_snbep.c | 38 ++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index e14b96398377..254ba0ad650a 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3837,14 +3837,14 @@ static void pmu_free_topology(struct intel_uncore_type *type)
 	}
 }
 
-static int skx_iio_get_topology(struct intel_uncore_type *type)
+static int skx_pmu_get_topology(struct intel_uncore_type *type,
+				 int (*topology_cb)(struct intel_uncore_type*, int, int, u64))
 {
 	int die, ret = -EPERM;
-	u64 configuration;
-	int idx;
+	u64 cpu_bus_msr;
 
 	for (die = 0; die < uncore_max_dies(); die++) {
-		ret = skx_msr_cpu_bus_read(die_to_cpu(die), &configuration);
+		ret = skx_msr_cpu_bus_read(die_to_cpu(die), &cpu_bus_msr);
 		if (ret)
 			break;
 
@@ -3852,17 +3852,35 @@ static int skx_iio_get_topology(struct intel_uncore_type *type)
 		if (ret < 0)
 			break;
 
-		for (idx = 0; idx < type->num_boxes; idx++) {
-			type->topology[die][idx].pmu_idx = idx;
-			type->topology[die][idx].iio->segment = ret;
-			type->topology[die][idx].iio->pci_bus_no =
-				(configuration >> (idx * BUS_NUM_STRIDE)) & 0xff;
-		}
+		ret = topology_cb(type, ret, die, cpu_bus_msr);
+		if (ret)
+			break;
 	}
 
 	return ret;
 }
 
+static int skx_iio_topology_cb(struct intel_uncore_type *type, int segment,
+				int die, u64 cpu_bus_msr)
+{
+	int idx;
+	struct intel_uncore_topology *t;
+
+	for (idx = 0; idx < type->num_boxes; idx++) {
+		t = &type->topology[die][idx];
+		t->pmu_idx = idx;
+		t->iio->segment = segment;
+		t->iio->pci_bus_no = (cpu_bus_msr >> (idx * BUS_NUM_STRIDE)) & 0xff;
+	}
+
+	return 0;
+}
+
+static int skx_iio_get_topology(struct intel_uncore_type *type)
+{
+	return skx_pmu_get_topology(type, skx_iio_topology_cb);
+}
+
 static struct attribute_group skx_iio_mapping_group = {
 	.is_visible	= skx_iio_mapping_visible,
 };
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 06/11] perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (4 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 05/11] perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 07/11] perf/x86/intel/uncore: Get UPI NodeID and GroupID alexander.antonov
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

UPI topology discovery relies on data from KTILP0 (offset 0x94) and
KTIPCSTS (offset 0x120) registers which reside under IIO bus(3) on
SKX/CLX.

This patch enable UPI topology discovery on Skylake Server. Topology is
exposed through attributes /sys/devices/uncore_upi_<pmu_idx>/dieX,
where dieX is file which holds "upi_<idx1>:die_<idx2>" connected to
this UPI link.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore_snbep.c | 130 +++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 254ba0ad650a..f682a9a0f562 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -4253,6 +4253,132 @@ static struct intel_uncore_ops skx_upi_uncore_pci_ops = {
 	.read_counter	= snbep_uncore_pci_read_counter,
 };
 
+static umode_t
+skx_upi_mapping_visible(struct kobject *kobj, struct attribute *attr, int die)
+{
+	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
+
+	return pmu->type->topology[die][pmu->pmu_idx].upi->enabled ? attr->mode : 0;
+}
+
+static ssize_t skx_upi_mapping_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
+	struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
+	long die = (long)ea->var;
+	struct uncore_upi_topology *upi = pmu->type->topology[die][pmu->pmu_idx].upi;
+
+	return sysfs_emit(buf, "upi_%d,die_%d\n", upi->pmu_idx_to, upi->die_to);
+}
+
+#define SKX_UPI_REG_DID			0x2058
+#define SKX_UPI_REGS_ADDR_DEVICE_LINK0	0x0e
+#define SKX_UPI_REGS_ADDR_FUNCTION	0x00
+
+/*
+ * UPI Link Parameter 0
+ * |  Bit  |  Default  |  Description
+ * | 19:16 |     0h    | base_nodeid - The NodeID of the sending socket.
+ * | 12:8  |    00h    | sending_port - The processor die port number of the sending port.
+ */
+#define SKX_KTILP0_OFFSET	0x94
+
+/*
+ * UPI Pcode Status. This register is used by PCode to store the link training status.
+ * |  Bit  |  Default  |  Description
+ * |   4   |     0h    | ll_status_valid — Bit indicates the valid training status
+ *                       logged from PCode to the BIOS.
+ */
+#define SKX_KTIPCSTS_OFFSET	0x120
+
+static int upi_fill_topology(struct pci_dev *dev, struct intel_uncore_topology *tp,
+			     int pmu_idx)
+{
+	int ret;
+	u32 upi_conf;
+	struct uncore_upi_topology *upi = tp->upi;
+
+	tp->pmu_idx = pmu_idx;
+	ret = pci_read_config_dword(dev, SKX_KTIPCSTS_OFFSET, &upi_conf);
+	if (ret) {
+		ret = pcibios_err_to_errno(ret);
+		goto err;
+	}
+	upi->enabled = (upi_conf >> 4) & 1;
+	if (upi->enabled) {
+		ret = pci_read_config_dword(dev, SKX_KTILP0_OFFSET,
+					    &upi_conf);
+		if (ret) {
+			ret = pcibios_err_to_errno(ret);
+			goto err;
+		}
+		upi->die_to = (upi_conf >> 16) & 0xf;
+		upi->pmu_idx_to = (upi_conf >> 8) & 0x1f;
+	}
+err:
+	return ret;
+}
+
+static int skx_upi_topology_cb(struct intel_uncore_type *type, int segment,
+				int die, u64 cpu_bus_msr)
+{
+	int idx, ret;
+	struct intel_uncore_topology *upi;
+	unsigned int devfn;
+	struct pci_dev *dev = NULL;
+	u8 bus = cpu_bus_msr >> (3 * BUS_NUM_STRIDE);
+
+	for (idx = 0; idx < type->num_boxes; idx++) {
+		upi = &type->topology[die][idx];
+		devfn = PCI_DEVFN(SKX_UPI_REGS_ADDR_DEVICE_LINK0 + idx,
+				  SKX_UPI_REGS_ADDR_FUNCTION);
+		dev = pci_get_domain_bus_and_slot(segment, bus, devfn);
+		if (dev) {
+			ret = upi_fill_topology(dev, upi, idx);
+			if (ret)
+				break;
+		}
+	}
+
+	pci_dev_put(dev);
+	return ret;
+}
+
+static int skx_upi_get_topology(struct intel_uncore_type *type)
+{
+	/* CPX case is not supported */
+	if (boot_cpu_data.x86_stepping == 11)
+		return -EPERM;
+
+	return skx_pmu_get_topology(type, skx_upi_topology_cb);
+}
+
+static struct attribute_group skx_upi_mapping_group = {
+	.is_visible	= skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *skx_upi_attr_update[] = {
+	&skx_upi_mapping_group,
+	NULL
+};
+
+static int
+pmu_upi_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+{
+	return pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
+}
+
+static int skx_upi_set_mapping(struct intel_uncore_type *type)
+{
+	return pmu_upi_set_mapping(type, &skx_upi_mapping_group);
+}
+
+static void skx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+	pmu_cleanup_mapping(type, &skx_upi_mapping_group);
+}
+
 static struct intel_uncore_type skx_uncore_upi = {
 	.name		= "upi",
 	.num_counters   = 4,
@@ -4265,6 +4391,10 @@ static struct intel_uncore_type skx_uncore_upi = {
 	.box_ctl	= SKX_UPI_PCI_PMON_BOX_CTL,
 	.ops		= &skx_upi_uncore_pci_ops,
 	.format_group	= &skx_upi_uncore_format_group,
+	.attr_update	= skx_upi_attr_update,
+	.get_topology	= skx_upi_get_topology,
+	.set_mapping	= skx_upi_set_mapping,
+	.cleanup_mapping = skx_upi_cleanup_mapping,
 };
 
 static void skx_m2m_uncore_pci_init_box(struct intel_uncore_box *box)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 07/11] perf/x86/intel/uncore: Get UPI NodeID and GroupID
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (5 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 06/11] perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 08/11] perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server alexander.antonov
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

The GIDNIDMAP register of UBOX device is used to get the topology
information in the snbep_pci2phy_map_init(). The same approach will be
used to discover UPI topology for ICX and SPR platforms.

Move common code that will be reused in next patches.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore_snbep.c | 33 +++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index f682a9a0f562..6da5f692afea 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -1372,6 +1372,28 @@ static struct pci_driver snbep_uncore_pci_driver = {
 
 #define NODE_ID_MASK	0x7
 
+/* Each three bits from 0 to 23 of GIDNIDMAP register correspond Node ID. */
+#define GIDNIDMAP(config, id)	(((config) >> (3 * (id))) & 0x7)
+
+static int upi_nodeid_groupid(struct pci_dev *ubox_dev, int nodeid_loc, int idmap_loc,
+			      int *nodeid, int *groupid)
+{
+	int ret;
+
+	/* get the Node ID of the local register */
+	ret = pci_read_config_dword(ubox_dev, nodeid_loc, nodeid);
+	if (ret)
+		goto err;
+
+	*nodeid = *nodeid & NODE_ID_MASK;
+	/* get the Node ID mapping */
+	ret = pci_read_config_dword(ubox_dev, idmap_loc, groupid);
+	if (ret)
+		goto err;
+err:
+	return ret;
+}
+
 /*
  * build pci bus to socket mapping
  */
@@ -1397,13 +1419,8 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
 		 * the topology.
 		 */
 		if (nr_node_ids <= 8) {
-			/* get the Node ID of the local register */
-			err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
-			if (err)
-				break;
-			nodeid = config & NODE_ID_MASK;
-			/* get the Node ID mapping */
-			err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
+			err = upi_nodeid_groupid(ubox_dev, nodeid_loc, idmap_loc,
+						 &nodeid, &config);
 			if (err)
 				break;
 
@@ -1421,7 +1438,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
 			 * to a particular node.
 			 */
 			for (i = 0; i < 8; i++) {
-				if (nodeid == ((config >> (3 * i)) & 0x7)) {
+				if (nodeid == GIDNIDMAP(config, i)) {
 					if (topology_max_die_per_package() > 1)
 						die_id = i;
 					else
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 08/11] perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (6 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 07/11] perf/x86/intel/uncore: Get UPI NodeID and GroupID alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 09/11] perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids alexander.antonov
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

UPI topology discovery relies on data from KTILP0 (offset 0x94) and
KTIPCSTS (offset 0x120) as well as on SKX but on Icelake Server these
registers reside under UBOX (Device ID 0x3450) bus.

This patch enables /sys/devices/uncore_upi_*/die* attributes on Icelake
Server.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore_snbep.c | 75 ++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 6da5f692afea..d45f5843444d 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -445,6 +445,7 @@
 #define ICX_UPI_PCI_PMON_CTR0			0x320
 #define ICX_UPI_PCI_PMON_BOX_CTL		0x318
 #define ICX_UPI_CTL_UMASK_EXT			0xffffff
+#define ICX_UBOX_DID				0x3450
 
 /* ICX M3UPI*/
 #define ICX_M3UPI_PCI_PMON_CTL0			0xd8
@@ -5594,6 +5595,76 @@ static const struct attribute_group icx_upi_uncore_format_group = {
 	.attrs = icx_upi_uncore_formats_attr,
 };
 
+#define ICX_UPI_REGS_ADDR_DEVICE_LINK0	0x02
+#define ICX_UPI_REGS_ADDR_FUNCTION	0x01
+
+static int discover_upi_topology(struct intel_uncore_type *type, int ubox_did, int dev_link0)
+{
+	struct pci_dev *ubox = NULL;
+	struct pci_dev *dev = NULL;
+	u32 nid, gid;
+	int i, idx, ret = -EPERM;
+	struct intel_uncore_topology *upi;
+	unsigned int devfn;
+
+	/* GIDNIDMAP method supports machines which have less than 8 sockets. */
+	if (uncore_max_dies() > 8)
+		goto err;
+
+	while ((ubox = pci_get_device(PCI_VENDOR_ID_INTEL, ubox_did, ubox))) {
+		ret = upi_nodeid_groupid(ubox, SKX_CPUNODEID, SKX_GIDNIDMAP, &nid, &gid);
+		if (ret) {
+			ret = pcibios_err_to_errno(ret);
+			break;
+		}
+
+		for (i = 0; i < 8; i++) {
+			if (nid != GIDNIDMAP(gid, i))
+				continue;
+			for (idx = 0; idx < type->num_boxes; idx++) {
+				upi = &type->topology[nid][idx];
+				devfn = PCI_DEVFN(dev_link0 + idx, ICX_UPI_REGS_ADDR_FUNCTION);
+				dev = pci_get_domain_bus_and_slot(pci_domain_nr(ubox->bus),
+								  ubox->bus->number,
+								  devfn);
+				if (dev) {
+					ret = upi_fill_topology(dev, upi, idx);
+					if (ret)
+						goto err;
+				}
+			}
+		}
+	}
+err:
+	pci_dev_put(ubox);
+	pci_dev_put(dev);
+	return ret;
+}
+
+static int icx_upi_get_topology(struct intel_uncore_type *type)
+{
+	return discover_upi_topology(type, ICX_UBOX_DID, ICX_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
+static struct attribute_group icx_upi_mapping_group = {
+	.is_visible	= skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *icx_upi_attr_update[] = {
+	&icx_upi_mapping_group,
+	NULL
+};
+
+static int icx_upi_set_mapping(struct intel_uncore_type *type)
+{
+	return pmu_upi_set_mapping(type, &icx_upi_mapping_group);
+}
+
+static void icx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+	pmu_cleanup_mapping(type, &icx_upi_mapping_group);
+}
+
 static struct intel_uncore_type icx_uncore_upi = {
 	.name		= "upi",
 	.num_counters   = 4,
@@ -5606,6 +5677,10 @@ static struct intel_uncore_type icx_uncore_upi = {
 	.box_ctl	= ICX_UPI_PCI_PMON_BOX_CTL,
 	.ops		= &skx_upi_uncore_pci_ops,
 	.format_group	= &icx_upi_uncore_format_group,
+	.attr_update	= icx_upi_attr_update,
+	.get_topology	= icx_upi_get_topology,
+	.set_mapping	= icx_upi_set_mapping,
+	.cleanup_mapping = icx_upi_cleanup_mapping,
 };
 
 static struct event_constraint icx_uncore_m3upi_constraints[] = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 09/11] perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (7 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 08/11] perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 10/11] perf/x86/intel/uncore: Update sysfs-devices-mapping file alexander.antonov
  2022-11-17 12:28 ` [PATCH 11/11] perf/x86/intel/uncore: Make set_mapping() procedure void alexander.antonov
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

UPI topology discovery on SPR is same as in ICX but UBOX device has
different Device ID 0x3250.

This patch enables /sys/devices/uncore_upi_*/die* attributes on SPR.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore_snbep.c | 43 +++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index d45f5843444d..4c2d5b5ea445 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -458,6 +458,7 @@
 
 /* SPR */
 #define SPR_RAW_EVENT_MASK_EXT			0xffffff
+#define SPR_UBOX_DID				0x3250
 
 /* SPR CHA */
 #define SPR_CHA_PMON_CTL_TID_EN			(1 << 16)
@@ -6112,9 +6113,43 @@ static struct intel_uncore_type spr_uncore_m2m = {
 	.name			= "m2m",
 };
 
+static struct attribute_group spr_upi_mapping_group = {
+	.is_visible	= skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *spr_upi_attr_update[] = {
+	&uncore_alias_group,
+	&spr_upi_mapping_group,
+	NULL
+};
+
+#define SPR_UPI_REGS_ADDR_DEVICE_LINK0	0x01
+
+static int spr_upi_set_mapping(struct intel_uncore_type *type)
+{
+	return pmu_upi_set_mapping(type, &spr_upi_mapping_group);
+}
+
+static void spr_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+	pmu_cleanup_mapping(type, &spr_upi_mapping_group);
+}
+
+static int spr_upi_get_topology(struct intel_uncore_type *type)
+{
+	return discover_upi_topology(type, SPR_UBOX_DID, SPR_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
 static struct intel_uncore_type spr_uncore_upi = {
-	SPR_UNCORE_PCI_COMMON_FORMAT(),
+	.event_mask		= SNBEP_PMON_RAW_EVENT_MASK,
+	.event_mask_ext		= SPR_RAW_EVENT_MASK_EXT,
+	.format_group		= &spr_uncore_raw_format_group,
+	.ops			= &spr_uncore_pci_ops,
 	.name			= "upi",
+	.attr_update		= spr_upi_attr_update,
+	.get_topology		= spr_upi_get_topology,
+	.set_mapping		= spr_upi_set_mapping,
+	.cleanup_mapping	= spr_upi_cleanup_mapping,
 };
 
 static struct intel_uncore_type spr_uncore_m3upi = {
@@ -6318,6 +6353,12 @@ static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
 		to_type->format_group = from_type->format_group;
 	if (from_type->attr_update)
 		to_type->attr_update = from_type->attr_update;
+	if (from_type->set_mapping)
+		to_type->set_mapping = from_type->set_mapping;
+	if (from_type->get_topology)
+		to_type->get_topology = from_type->get_topology;
+	if (from_type->cleanup_mapping)
+		to_type->cleanup_mapping = from_type->cleanup_mapping;
 }
 
 static struct intel_uncore_type **
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 10/11] perf/x86/intel/uncore: Update sysfs-devices-mapping file
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (8 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 09/11] perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  2022-11-17 12:28 ` [PATCH 11/11] perf/x86/intel/uncore: Make set_mapping() procedure void alexander.antonov
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Add description for /sys/devices/uncore_upi_*/die* attributes to
sysfs-devices-mapping.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 .../ABI/testing/sysfs-devices-mapping         | 30 ++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-devices-mapping b/Documentation/ABI/testing/sysfs-devices-mapping
index 8d202bac9394..2eee1446ad4c 100644
--- a/Documentation/ABI/testing/sysfs-devices-mapping
+++ b/Documentation/ABI/testing/sysfs-devices-mapping
@@ -1,6 +1,6 @@
 What:           /sys/devices/uncore_iio_x/dieX
 Date:           February 2020
-Contact:        Roman Sudarikov <roman.sudarikov@linux.intel.com>
+Contact:        Alexander Antonov <alexander.antonov@linux.intel.com>
 Description:
                 Each IIO stack (PCIe root port) has its own IIO PMON block, so
                 each dieX file (where X is die number) holds "Segment:Root Bus"
@@ -32,3 +32,31 @@ Description:
 		    IIO PMU 0 on die 1 belongs to PCI RP on bus 0x40, domain 0x0000
 		    IIO PMU 0 on die 2 belongs to PCI RP on bus 0x80, domain 0x0000
 		    IIO PMU 0 on die 3 belongs to PCI RP on bus 0xc0, domain 0x0000
+
+What:           /sys/devices/uncore_upi_x/dieX
+Date:           March 2022
+Contact:        Alexander Antonov <alexander.antonov@linux.intel.com>
+Description:
+                Each /sys/devices/uncore_upi_X/dieY file holds "upi_Z,die_W"
+                value that means UPI link number X on die Y is connected to UPI
+                link Z on die W and this link between sockets can be monitored
+                by UPI PMON block.
+                For example, 4-die Sapphire Rapids platform has the following
+                UPI 0 topology::
+
+		    # tail /sys/devices/uncore_upi_0/die*
+		    ==> /sys/devices/uncore_upi_0/die0 <==
+		    upi_1,die_1
+		    ==> /sys/devices/uncore_upi_0/die1 <==
+		    upi_0,die_3
+		    ==> /sys/devices/uncore_upi_0/die2 <==
+		    upi_1,die_3
+		    ==> /sys/devices/uncore_upi_0/die3 <==
+		    upi_0,die_1
+
+                Which means::
+
+		    UPI link 0 on die 0 is connected to UPI link 1 on die 1
+		    UPI link 0 on die 1 is connected to UPI link 0 on die 3
+		    UPI link 0 on die 2 is connected to UPI link 1 on die 3
+		    UPI link 0 on die 3 is connected to UPI link 0 on die 1
\ No newline at end of file
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [PATCH 11/11] perf/x86/intel/uncore: Make set_mapping() procedure void
  2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
                   ` (9 preceding siblings ...)
  2022-11-17 12:28 ` [PATCH 10/11] perf/x86/intel/uncore: Update sysfs-devices-mapping file alexander.antonov
@ 2022-11-17 12:28 ` alexander.antonov
  2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
  10 siblings, 1 reply; 23+ messages in thread
From: alexander.antonov @ 2022-11-17 12:28 UTC (permalink / raw)
  To: peterz, linux-kernel; +Cc: kan.liang, alexey.v.bayduraev, alexander.antonov

From: Alexander Antonov <alexander.antonov@linux.intel.com>

Return value of set_mapping() is not needed to be checked anymore.
So, make this procedure void.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/uncore.h       |  2 +-
 arch/x86/events/intel/uncore_snbep.c | 41 +++++++++++++---------------
 2 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index fac3612289f1..e278e2e7c051 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -94,7 +94,7 @@ struct intel_uncore_type {
 	 * Optional callbacks for managing mapping of Uncore units to PMONs
 	 */
 	int (*get_topology)(struct intel_uncore_type *type);
-	int (*set_mapping)(struct intel_uncore_type *type);
+	void (*set_mapping)(struct intel_uncore_type *type);
 	void (*cleanup_mapping)(struct intel_uncore_type *type);
 };
 
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 4c2d5b5ea445..b8f9bd150b42 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3924,7 +3924,7 @@ static void pmu_clear_mapping_attr(const struct attribute_group **groups,
 	}
 }
 
-static int
+static void
 pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 		ssize_t (*show)(struct device*, struct device_attribute*, char*),
 		int topology_type)
@@ -3943,8 +3943,6 @@ pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 	if (ret < 0)
 		goto clear_topology;
 
-	ret = -ENOMEM;
-
 	/* One more for NULL. */
 	attrs = kcalloc((uncore_max_dies() + 1), sizeof(*attrs), GFP_KERNEL);
 	if (!attrs)
@@ -3968,7 +3966,7 @@ pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 	}
 	ag->attrs = attrs;
 
-	return 0;
+	return;
 err:
 	for (; die >= 0; die--)
 		kfree(eas[die].attr.attr.name);
@@ -3979,7 +3977,6 @@ pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 	pmu_free_topology(type);
 clear_attr_update:
 	pmu_clear_mapping_attr(type->attr_update, ag);
-	return ret;
 }
 
 static void
@@ -3998,15 +3995,15 @@ pmu_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 	pmu_free_topology(type);
 }
 
-static int
+static void
 pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 {
-	return pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
+	pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
 }
 
-static int skx_iio_set_mapping(struct intel_uncore_type *type)
+static void skx_iio_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_iio_set_mapping(type, &skx_iio_mapping_group);
+	pmu_iio_set_mapping(type, &skx_iio_mapping_group);
 }
 
 static void skx_iio_cleanup_mapping(struct intel_uncore_type *type)
@@ -4382,15 +4379,15 @@ static const struct attribute_group *skx_upi_attr_update[] = {
 	NULL
 };
 
-static int
+static void
 pmu_upi_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 {
-	return pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
+	pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
 }
 
-static int skx_upi_set_mapping(struct intel_uncore_type *type)
+static void skx_upi_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_upi_set_mapping(type, &skx_upi_mapping_group);
+	pmu_upi_set_mapping(type, &skx_upi_mapping_group);
 }
 
 static void skx_upi_cleanup_mapping(struct intel_uncore_type *type)
@@ -4773,9 +4770,9 @@ static int snr_iio_get_topology(struct intel_uncore_type *type)
 	return sad_cfg_iio_topology(type, snr_sad_pmon_mapping);
 }
 
-static int snr_iio_set_mapping(struct intel_uncore_type *type)
+static void snr_iio_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_iio_set_mapping(type, &snr_iio_mapping_group);
+	pmu_iio_set_mapping(type, &snr_iio_mapping_group);
 }
 
 static void snr_iio_cleanup_mapping(struct intel_uncore_type *type)
@@ -5391,14 +5388,14 @@ static int icx_iio_get_topology(struct intel_uncore_type *type)
 	return sad_cfg_iio_topology(type, icx_sad_pmon_mapping);
 }
 
-static int icx_iio_set_mapping(struct intel_uncore_type *type)
+static void icx_iio_set_mapping(struct intel_uncore_type *type)
 {
 	/* Detect ICX-D system. This case is not supported */
 	if (boot_cpu_data.x86_model == INTEL_FAM6_ICELAKE_D) {
 		pmu_clear_mapping_attr(type->attr_update, &icx_iio_mapping_group);
-		return -EPERM;
+		return;
 	}
-	return pmu_iio_set_mapping(type, &icx_iio_mapping_group);
+	pmu_iio_set_mapping(type, &icx_iio_mapping_group);
 }
 
 static void icx_iio_cleanup_mapping(struct intel_uncore_type *type)
@@ -5656,9 +5653,9 @@ static const struct attribute_group *icx_upi_attr_update[] = {
 	NULL
 };
 
-static int icx_upi_set_mapping(struct intel_uncore_type *type)
+static void icx_upi_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_upi_set_mapping(type, &icx_upi_mapping_group);
+	pmu_upi_set_mapping(type, &icx_upi_mapping_group);
 }
 
 static void icx_upi_cleanup_mapping(struct intel_uncore_type *type)
@@ -6125,9 +6122,9 @@ static const struct attribute_group *spr_upi_attr_update[] = {
 
 #define SPR_UPI_REGS_ADDR_DEVICE_LINK0	0x01
 
-static int spr_upi_set_mapping(struct intel_uncore_type *type)
+static void spr_upi_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_upi_set_mapping(type, &spr_upi_mapping_group);
+	pmu_upi_set_mapping(type, &spr_upi_mapping_group);
 }
 
 static void spr_upi_cleanup_mapping(struct intel_uncore_type *type)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Make set_mapping() procedure void
  2022-11-17 12:28 ` [PATCH 11/11] perf/x86/intel/uncore: Make set_mapping() procedure void alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     d5b73506b5b1b4a6e675c54b7977ea08e64cba19
Gitweb:        https://git.kernel.org/tip/d5b73506b5b1b4a6e675c54b7977ea08e64cba19
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:33 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:24 +01:00

perf/x86/intel/uncore: Make set_mapping() procedure void

Return value of set_mapping() is not needed to be checked anymore.
So, make this procedure void.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-12-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore.h       |  2 +-
 arch/x86/events/intel/uncore_snbep.c | 41 ++++++++++++---------------
 2 files changed, 20 insertions(+), 23 deletions(-)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index fac3612..e278e2e 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -94,7 +94,7 @@ struct intel_uncore_type {
 	 * Optional callbacks for managing mapping of Uncore units to PMONs
 	 */
 	int (*get_topology)(struct intel_uncore_type *type);
-	int (*set_mapping)(struct intel_uncore_type *type);
+	void (*set_mapping)(struct intel_uncore_type *type);
 	void (*cleanup_mapping)(struct intel_uncore_type *type);
 };
 
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 4c2d5b5..b8f9bd1 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3924,7 +3924,7 @@ static void pmu_clear_mapping_attr(const struct attribute_group **groups,
 	}
 }
 
-static int
+static void
 pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 		ssize_t (*show)(struct device*, struct device_attribute*, char*),
 		int topology_type)
@@ -3943,8 +3943,6 @@ pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 	if (ret < 0)
 		goto clear_topology;
 
-	ret = -ENOMEM;
-
 	/* One more for NULL. */
 	attrs = kcalloc((uncore_max_dies() + 1), sizeof(*attrs), GFP_KERNEL);
 	if (!attrs)
@@ -3968,7 +3966,7 @@ pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 	}
 	ag->attrs = attrs;
 
-	return 0;
+	return;
 err:
 	for (; die >= 0; die--)
 		kfree(eas[die].attr.attr.name);
@@ -3979,7 +3977,6 @@ clear_topology:
 	pmu_free_topology(type);
 clear_attr_update:
 	pmu_clear_mapping_attr(type->attr_update, ag);
-	return ret;
 }
 
 static void
@@ -3998,15 +3995,15 @@ pmu_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 	pmu_free_topology(type);
 }
 
-static int
+static void
 pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 {
-	return pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
+	pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
 }
 
-static int skx_iio_set_mapping(struct intel_uncore_type *type)
+static void skx_iio_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_iio_set_mapping(type, &skx_iio_mapping_group);
+	pmu_iio_set_mapping(type, &skx_iio_mapping_group);
 }
 
 static void skx_iio_cleanup_mapping(struct intel_uncore_type *type)
@@ -4382,15 +4379,15 @@ static const struct attribute_group *skx_upi_attr_update[] = {
 	NULL
 };
 
-static int
+static void
 pmu_upi_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 {
-	return pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
+	pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
 }
 
-static int skx_upi_set_mapping(struct intel_uncore_type *type)
+static void skx_upi_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_upi_set_mapping(type, &skx_upi_mapping_group);
+	pmu_upi_set_mapping(type, &skx_upi_mapping_group);
 }
 
 static void skx_upi_cleanup_mapping(struct intel_uncore_type *type)
@@ -4773,9 +4770,9 @@ static int snr_iio_get_topology(struct intel_uncore_type *type)
 	return sad_cfg_iio_topology(type, snr_sad_pmon_mapping);
 }
 
-static int snr_iio_set_mapping(struct intel_uncore_type *type)
+static void snr_iio_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_iio_set_mapping(type, &snr_iio_mapping_group);
+	pmu_iio_set_mapping(type, &snr_iio_mapping_group);
 }
 
 static void snr_iio_cleanup_mapping(struct intel_uncore_type *type)
@@ -5391,14 +5388,14 @@ static int icx_iio_get_topology(struct intel_uncore_type *type)
 	return sad_cfg_iio_topology(type, icx_sad_pmon_mapping);
 }
 
-static int icx_iio_set_mapping(struct intel_uncore_type *type)
+static void icx_iio_set_mapping(struct intel_uncore_type *type)
 {
 	/* Detect ICX-D system. This case is not supported */
 	if (boot_cpu_data.x86_model == INTEL_FAM6_ICELAKE_D) {
 		pmu_clear_mapping_attr(type->attr_update, &icx_iio_mapping_group);
-		return -EPERM;
+		return;
 	}
-	return pmu_iio_set_mapping(type, &icx_iio_mapping_group);
+	pmu_iio_set_mapping(type, &icx_iio_mapping_group);
 }
 
 static void icx_iio_cleanup_mapping(struct intel_uncore_type *type)
@@ -5656,9 +5653,9 @@ static const struct attribute_group *icx_upi_attr_update[] = {
 	NULL
 };
 
-static int icx_upi_set_mapping(struct intel_uncore_type *type)
+static void icx_upi_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_upi_set_mapping(type, &icx_upi_mapping_group);
+	pmu_upi_set_mapping(type, &icx_upi_mapping_group);
 }
 
 static void icx_upi_cleanup_mapping(struct intel_uncore_type *type)
@@ -6125,9 +6122,9 @@ static const struct attribute_group *spr_upi_attr_update[] = {
 
 #define SPR_UPI_REGS_ADDR_DEVICE_LINK0	0x01
 
-static int spr_upi_set_mapping(struct intel_uncore_type *type)
+static void spr_upi_set_mapping(struct intel_uncore_type *type)
 {
-	return pmu_upi_set_mapping(type, &spr_upi_mapping_group);
+	pmu_upi_set_mapping(type, &spr_upi_mapping_group);
 }
 
 static void spr_upi_cleanup_mapping(struct intel_uncore_type *type)

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Update sysfs-devices-mapping file
  2022-11-17 12:28 ` [PATCH 10/11] perf/x86/intel/uncore: Update sysfs-devices-mapping file alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     61fb0f7e974ac00ead611c00a57efdafac7785b5
Gitweb:        https://git.kernel.org/tip/61fb0f7e974ac00ead611c00a57efdafac7785b5
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:32 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:24 +01:00

perf/x86/intel/uncore: Update sysfs-devices-mapping file

Add description for /sys/devices/uncore_upi_*/die* attributes to
sysfs-devices-mapping.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-11-alexander.antonov@linux.intel.com
---
 Documentation/ABI/testing/sysfs-devices-mapping | 30 +++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-devices-mapping b/Documentation/ABI/testing/sysfs-devices-mapping
index 8d202ba..2eee144 100644
--- a/Documentation/ABI/testing/sysfs-devices-mapping
+++ b/Documentation/ABI/testing/sysfs-devices-mapping
@@ -1,6 +1,6 @@
 What:           /sys/devices/uncore_iio_x/dieX
 Date:           February 2020
-Contact:        Roman Sudarikov <roman.sudarikov@linux.intel.com>
+Contact:        Alexander Antonov <alexander.antonov@linux.intel.com>
 Description:
                 Each IIO stack (PCIe root port) has its own IIO PMON block, so
                 each dieX file (where X is die number) holds "Segment:Root Bus"
@@ -32,3 +32,31 @@ Description:
 		    IIO PMU 0 on die 1 belongs to PCI RP on bus 0x40, domain 0x0000
 		    IIO PMU 0 on die 2 belongs to PCI RP on bus 0x80, domain 0x0000
 		    IIO PMU 0 on die 3 belongs to PCI RP on bus 0xc0, domain 0x0000
+
+What:           /sys/devices/uncore_upi_x/dieX
+Date:           March 2022
+Contact:        Alexander Antonov <alexander.antonov@linux.intel.com>
+Description:
+                Each /sys/devices/uncore_upi_X/dieY file holds "upi_Z,die_W"
+                value that means UPI link number X on die Y is connected to UPI
+                link Z on die W and this link between sockets can be monitored
+                by UPI PMON block.
+                For example, 4-die Sapphire Rapids platform has the following
+                UPI 0 topology::
+
+		    # tail /sys/devices/uncore_upi_0/die*
+		    ==> /sys/devices/uncore_upi_0/die0 <==
+		    upi_1,die_1
+		    ==> /sys/devices/uncore_upi_0/die1 <==
+		    upi_0,die_3
+		    ==> /sys/devices/uncore_upi_0/die2 <==
+		    upi_1,die_3
+		    ==> /sys/devices/uncore_upi_0/die3 <==
+		    upi_0,die_1
+
+                Which means::
+
+		    UPI link 0 on die 0 is connected to UPI link 1 on die 1
+		    UPI link 0 on die 1 is connected to UPI link 0 on die 3
+		    UPI link 0 on die 2 is connected to UPI link 1 on die 3
+		    UPI link 0 on die 3 is connected to UPI link 0 on die 1
\ No newline at end of file

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids
  2022-11-17 12:28 ` [PATCH 09/11] perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     9a3b675cd393a4430d5e6cbf94c5de43414613cd
Gitweb:        https://git.kernel.org/tip/9a3b675cd393a4430d5e6cbf94c5de43414613cd
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:31 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:23 +01:00

perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids

UPI topology discovery on SPR is same as in ICX but UBOX device has
different Device ID 0x3250.

This patch enables /sys/devices/uncore_upi_*/die* attributes on SPR.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-10-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore_snbep.c | 43 ++++++++++++++++++++++++++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index d45f584..4c2d5b5 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -458,6 +458,7 @@
 
 /* SPR */
 #define SPR_RAW_EVENT_MASK_EXT			0xffffff
+#define SPR_UBOX_DID				0x3250
 
 /* SPR CHA */
 #define SPR_CHA_PMON_CTL_TID_EN			(1 << 16)
@@ -6112,9 +6113,43 @@ static struct intel_uncore_type spr_uncore_m2m = {
 	.name			= "m2m",
 };
 
+static struct attribute_group spr_upi_mapping_group = {
+	.is_visible	= skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *spr_upi_attr_update[] = {
+	&uncore_alias_group,
+	&spr_upi_mapping_group,
+	NULL
+};
+
+#define SPR_UPI_REGS_ADDR_DEVICE_LINK0	0x01
+
+static int spr_upi_set_mapping(struct intel_uncore_type *type)
+{
+	return pmu_upi_set_mapping(type, &spr_upi_mapping_group);
+}
+
+static void spr_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+	pmu_cleanup_mapping(type, &spr_upi_mapping_group);
+}
+
+static int spr_upi_get_topology(struct intel_uncore_type *type)
+{
+	return discover_upi_topology(type, SPR_UBOX_DID, SPR_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
 static struct intel_uncore_type spr_uncore_upi = {
-	SPR_UNCORE_PCI_COMMON_FORMAT(),
+	.event_mask		= SNBEP_PMON_RAW_EVENT_MASK,
+	.event_mask_ext		= SPR_RAW_EVENT_MASK_EXT,
+	.format_group		= &spr_uncore_raw_format_group,
+	.ops			= &spr_uncore_pci_ops,
 	.name			= "upi",
+	.attr_update		= spr_upi_attr_update,
+	.get_topology		= spr_upi_get_topology,
+	.set_mapping		= spr_upi_set_mapping,
+	.cleanup_mapping	= spr_upi_cleanup_mapping,
 };
 
 static struct intel_uncore_type spr_uncore_m3upi = {
@@ -6318,6 +6353,12 @@ static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
 		to_type->format_group = from_type->format_group;
 	if (from_type->attr_update)
 		to_type->attr_update = from_type->attr_update;
+	if (from_type->set_mapping)
+		to_type->set_mapping = from_type->set_mapping;
+	if (from_type->get_topology)
+		to_type->get_topology = from_type->get_topology;
+	if (from_type->cleanup_mapping)
+		to_type->cleanup_mapping = from_type->cleanup_mapping;
 }
 
 static struct intel_uncore_type **

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server
  2022-11-17 12:28 ` [PATCH 08/11] perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     f680b6e6062ef3c944ffc966d685f067958fca33
Gitweb:        https://git.kernel.org/tip/f680b6e6062ef3c944ffc966d685f067958fca33
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:30 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:23 +01:00

perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server

UPI topology discovery relies on data from KTILP0 (offset 0x94) and
KTIPCSTS (offset 0x120) as well as on SKX but on Icelake Server these
registers reside under UBOX (Device ID 0x3450) bus.

This patch enables /sys/devices/uncore_upi_*/die* attributes on Icelake
Server.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-9-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore_snbep.c | 75 +++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 6da5f69..d45f584 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -445,6 +445,7 @@
 #define ICX_UPI_PCI_PMON_CTR0			0x320
 #define ICX_UPI_PCI_PMON_BOX_CTL		0x318
 #define ICX_UPI_CTL_UMASK_EXT			0xffffff
+#define ICX_UBOX_DID				0x3450
 
 /* ICX M3UPI*/
 #define ICX_M3UPI_PCI_PMON_CTL0			0xd8
@@ -5594,6 +5595,76 @@ static const struct attribute_group icx_upi_uncore_format_group = {
 	.attrs = icx_upi_uncore_formats_attr,
 };
 
+#define ICX_UPI_REGS_ADDR_DEVICE_LINK0	0x02
+#define ICX_UPI_REGS_ADDR_FUNCTION	0x01
+
+static int discover_upi_topology(struct intel_uncore_type *type, int ubox_did, int dev_link0)
+{
+	struct pci_dev *ubox = NULL;
+	struct pci_dev *dev = NULL;
+	u32 nid, gid;
+	int i, idx, ret = -EPERM;
+	struct intel_uncore_topology *upi;
+	unsigned int devfn;
+
+	/* GIDNIDMAP method supports machines which have less than 8 sockets. */
+	if (uncore_max_dies() > 8)
+		goto err;
+
+	while ((ubox = pci_get_device(PCI_VENDOR_ID_INTEL, ubox_did, ubox))) {
+		ret = upi_nodeid_groupid(ubox, SKX_CPUNODEID, SKX_GIDNIDMAP, &nid, &gid);
+		if (ret) {
+			ret = pcibios_err_to_errno(ret);
+			break;
+		}
+
+		for (i = 0; i < 8; i++) {
+			if (nid != GIDNIDMAP(gid, i))
+				continue;
+			for (idx = 0; idx < type->num_boxes; idx++) {
+				upi = &type->topology[nid][idx];
+				devfn = PCI_DEVFN(dev_link0 + idx, ICX_UPI_REGS_ADDR_FUNCTION);
+				dev = pci_get_domain_bus_and_slot(pci_domain_nr(ubox->bus),
+								  ubox->bus->number,
+								  devfn);
+				if (dev) {
+					ret = upi_fill_topology(dev, upi, idx);
+					if (ret)
+						goto err;
+				}
+			}
+		}
+	}
+err:
+	pci_dev_put(ubox);
+	pci_dev_put(dev);
+	return ret;
+}
+
+static int icx_upi_get_topology(struct intel_uncore_type *type)
+{
+	return discover_upi_topology(type, ICX_UBOX_DID, ICX_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
+static struct attribute_group icx_upi_mapping_group = {
+	.is_visible	= skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *icx_upi_attr_update[] = {
+	&icx_upi_mapping_group,
+	NULL
+};
+
+static int icx_upi_set_mapping(struct intel_uncore_type *type)
+{
+	return pmu_upi_set_mapping(type, &icx_upi_mapping_group);
+}
+
+static void icx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+	pmu_cleanup_mapping(type, &icx_upi_mapping_group);
+}
+
 static struct intel_uncore_type icx_uncore_upi = {
 	.name		= "upi",
 	.num_counters   = 4,
@@ -5606,6 +5677,10 @@ static struct intel_uncore_type icx_uncore_upi = {
 	.box_ctl	= ICX_UPI_PCI_PMON_BOX_CTL,
 	.ops		= &skx_upi_uncore_pci_ops,
 	.format_group	= &icx_upi_uncore_format_group,
+	.attr_update	= icx_upi_attr_update,
+	.get_topology	= icx_upi_get_topology,
+	.set_mapping	= icx_upi_set_mapping,
+	.cleanup_mapping = icx_upi_cleanup_mapping,
 };
 
 static struct event_constraint icx_uncore_m3upi_constraints[] = {

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Get UPI NodeID and GroupID
  2022-11-17 12:28 ` [PATCH 07/11] perf/x86/intel/uncore: Get UPI NodeID and GroupID alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     c4aebdb3b5f50fd0d83bf0fc2d49ac299f8b61df
Gitweb:        https://git.kernel.org/tip/c4aebdb3b5f50fd0d83bf0fc2d49ac299f8b61df
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:29 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:22 +01:00

perf/x86/intel/uncore: Get UPI NodeID and GroupID

The GIDNIDMAP register of UBOX device is used to get the topology
information in the snbep_pci2phy_map_init(). The same approach will be
used to discover UPI topology for ICX and SPR platforms.

Move common code that will be reused in next patches.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-8-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore_snbep.c | 33 ++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index f682a9a..6da5f69 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -1372,6 +1372,28 @@ static struct pci_driver snbep_uncore_pci_driver = {
 
 #define NODE_ID_MASK	0x7
 
+/* Each three bits from 0 to 23 of GIDNIDMAP register correspond Node ID. */
+#define GIDNIDMAP(config, id)	(((config) >> (3 * (id))) & 0x7)
+
+static int upi_nodeid_groupid(struct pci_dev *ubox_dev, int nodeid_loc, int idmap_loc,
+			      int *nodeid, int *groupid)
+{
+	int ret;
+
+	/* get the Node ID of the local register */
+	ret = pci_read_config_dword(ubox_dev, nodeid_loc, nodeid);
+	if (ret)
+		goto err;
+
+	*nodeid = *nodeid & NODE_ID_MASK;
+	/* get the Node ID mapping */
+	ret = pci_read_config_dword(ubox_dev, idmap_loc, groupid);
+	if (ret)
+		goto err;
+err:
+	return ret;
+}
+
 /*
  * build pci bus to socket mapping
  */
@@ -1397,13 +1419,8 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
 		 * the topology.
 		 */
 		if (nr_node_ids <= 8) {
-			/* get the Node ID of the local register */
-			err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
-			if (err)
-				break;
-			nodeid = config & NODE_ID_MASK;
-			/* get the Node ID mapping */
-			err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
+			err = upi_nodeid_groupid(ubox_dev, nodeid_loc, idmap_loc,
+						 &nodeid, &config);
 			if (err)
 				break;
 
@@ -1421,7 +1438,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
 			 * to a particular node.
 			 */
 			for (i = 0; i < 8; i++) {
-				if (nodeid == ((config >> (3 * i)) & 0x7)) {
+				if (nodeid == GIDNIDMAP(config, i)) {
 					if (topology_max_die_per_package() > 1)
 						die_id = i;
 					else

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server
  2022-11-17 12:28 ` [PATCH 06/11] perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     4cfce57fa42d277497cd2c425021312eae2f223c
Gitweb:        https://git.kernel.org/tip/4cfce57fa42d277497cd2c425021312eae2f223c
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:28 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:22 +01:00

perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server

UPI topology discovery relies on data from KTILP0 (offset 0x94) and
KTIPCSTS (offset 0x120) registers which reside under IIO bus(3) on
SKX/CLX.

This patch enable UPI topology discovery on Skylake Server. Topology is
exposed through attributes /sys/devices/uncore_upi_<pmu_idx>/dieX,
where dieX is file which holds "upi_<idx1>:die_<idx2>" connected to
this UPI link.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-7-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore_snbep.c | 130 ++++++++++++++++++++++++++-
 1 file changed, 130 insertions(+)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 254ba0a..f682a9a 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -4253,6 +4253,132 @@ static struct intel_uncore_ops skx_upi_uncore_pci_ops = {
 	.read_counter	= snbep_uncore_pci_read_counter,
 };
 
+static umode_t
+skx_upi_mapping_visible(struct kobject *kobj, struct attribute *attr, int die)
+{
+	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
+
+	return pmu->type->topology[die][pmu->pmu_idx].upi->enabled ? attr->mode : 0;
+}
+
+static ssize_t skx_upi_mapping_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
+	struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
+	long die = (long)ea->var;
+	struct uncore_upi_topology *upi = pmu->type->topology[die][pmu->pmu_idx].upi;
+
+	return sysfs_emit(buf, "upi_%d,die_%d\n", upi->pmu_idx_to, upi->die_to);
+}
+
+#define SKX_UPI_REG_DID			0x2058
+#define SKX_UPI_REGS_ADDR_DEVICE_LINK0	0x0e
+#define SKX_UPI_REGS_ADDR_FUNCTION	0x00
+
+/*
+ * UPI Link Parameter 0
+ * |  Bit  |  Default  |  Description
+ * | 19:16 |     0h    | base_nodeid - The NodeID of the sending socket.
+ * | 12:8  |    00h    | sending_port - The processor die port number of the sending port.
+ */
+#define SKX_KTILP0_OFFSET	0x94
+
+/*
+ * UPI Pcode Status. This register is used by PCode to store the link training status.
+ * |  Bit  |  Default  |  Description
+ * |   4   |     0h    | ll_status_valid — Bit indicates the valid training status
+ *                       logged from PCode to the BIOS.
+ */
+#define SKX_KTIPCSTS_OFFSET	0x120
+
+static int upi_fill_topology(struct pci_dev *dev, struct intel_uncore_topology *tp,
+			     int pmu_idx)
+{
+	int ret;
+	u32 upi_conf;
+	struct uncore_upi_topology *upi = tp->upi;
+
+	tp->pmu_idx = pmu_idx;
+	ret = pci_read_config_dword(dev, SKX_KTIPCSTS_OFFSET, &upi_conf);
+	if (ret) {
+		ret = pcibios_err_to_errno(ret);
+		goto err;
+	}
+	upi->enabled = (upi_conf >> 4) & 1;
+	if (upi->enabled) {
+		ret = pci_read_config_dword(dev, SKX_KTILP0_OFFSET,
+					    &upi_conf);
+		if (ret) {
+			ret = pcibios_err_to_errno(ret);
+			goto err;
+		}
+		upi->die_to = (upi_conf >> 16) & 0xf;
+		upi->pmu_idx_to = (upi_conf >> 8) & 0x1f;
+	}
+err:
+	return ret;
+}
+
+static int skx_upi_topology_cb(struct intel_uncore_type *type, int segment,
+				int die, u64 cpu_bus_msr)
+{
+	int idx, ret;
+	struct intel_uncore_topology *upi;
+	unsigned int devfn;
+	struct pci_dev *dev = NULL;
+	u8 bus = cpu_bus_msr >> (3 * BUS_NUM_STRIDE);
+
+	for (idx = 0; idx < type->num_boxes; idx++) {
+		upi = &type->topology[die][idx];
+		devfn = PCI_DEVFN(SKX_UPI_REGS_ADDR_DEVICE_LINK0 + idx,
+				  SKX_UPI_REGS_ADDR_FUNCTION);
+		dev = pci_get_domain_bus_and_slot(segment, bus, devfn);
+		if (dev) {
+			ret = upi_fill_topology(dev, upi, idx);
+			if (ret)
+				break;
+		}
+	}
+
+	pci_dev_put(dev);
+	return ret;
+}
+
+static int skx_upi_get_topology(struct intel_uncore_type *type)
+{
+	/* CPX case is not supported */
+	if (boot_cpu_data.x86_stepping == 11)
+		return -EPERM;
+
+	return skx_pmu_get_topology(type, skx_upi_topology_cb);
+}
+
+static struct attribute_group skx_upi_mapping_group = {
+	.is_visible	= skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *skx_upi_attr_update[] = {
+	&skx_upi_mapping_group,
+	NULL
+};
+
+static int
+pmu_upi_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+{
+	return pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
+}
+
+static int skx_upi_set_mapping(struct intel_uncore_type *type)
+{
+	return pmu_upi_set_mapping(type, &skx_upi_mapping_group);
+}
+
+static void skx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+	pmu_cleanup_mapping(type, &skx_upi_mapping_group);
+}
+
 static struct intel_uncore_type skx_uncore_upi = {
 	.name		= "upi",
 	.num_counters   = 4,
@@ -4265,6 +4391,10 @@ static struct intel_uncore_type skx_uncore_upi = {
 	.box_ctl	= SKX_UPI_PCI_PMON_BOX_CTL,
 	.ops		= &skx_upi_uncore_pci_ops,
 	.format_group	= &skx_upi_uncore_format_group,
+	.attr_update	= skx_upi_attr_update,
+	.get_topology	= skx_upi_get_topology,
+	.set_mapping	= skx_upi_set_mapping,
+	.cleanup_mapping = skx_upi_cleanup_mapping,
 };
 
 static void skx_m2m_uncore_pci_init_box(struct intel_uncore_box *box)

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs
  2022-11-17 12:28 ` [PATCH 05/11] perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     07813e2a59c93f10716ffa33d608d2c0685cf85b
Gitweb:        https://git.kernel.org/tip/07813e2a59c93f10716ffa33d608d2c0685cf85b
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:27 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:22 +01:00

perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs

Factor out a generic code from skx_iio_get_topology() to skx_pmu_get_topology()
to avoid code duplication. This code will be used by get_topology() procedure
for SKX UPI PMUs in the further patch.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-6-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore_snbep.c | 38 +++++++++++++++++++--------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index e14b963..254ba0a 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3837,14 +3837,14 @@ static void pmu_free_topology(struct intel_uncore_type *type)
 	}
 }
 
-static int skx_iio_get_topology(struct intel_uncore_type *type)
+static int skx_pmu_get_topology(struct intel_uncore_type *type,
+				 int (*topology_cb)(struct intel_uncore_type*, int, int, u64))
 {
 	int die, ret = -EPERM;
-	u64 configuration;
-	int idx;
+	u64 cpu_bus_msr;
 
 	for (die = 0; die < uncore_max_dies(); die++) {
-		ret = skx_msr_cpu_bus_read(die_to_cpu(die), &configuration);
+		ret = skx_msr_cpu_bus_read(die_to_cpu(die), &cpu_bus_msr);
 		if (ret)
 			break;
 
@@ -3852,17 +3852,35 @@ static int skx_iio_get_topology(struct intel_uncore_type *type)
 		if (ret < 0)
 			break;
 
-		for (idx = 0; idx < type->num_boxes; idx++) {
-			type->topology[die][idx].pmu_idx = idx;
-			type->topology[die][idx].iio->segment = ret;
-			type->topology[die][idx].iio->pci_bus_no =
-				(configuration >> (idx * BUS_NUM_STRIDE)) & 0xff;
-		}
+		ret = topology_cb(type, ret, die, cpu_bus_msr);
+		if (ret)
+			break;
 	}
 
 	return ret;
 }
 
+static int skx_iio_topology_cb(struct intel_uncore_type *type, int segment,
+				int die, u64 cpu_bus_msr)
+{
+	int idx;
+	struct intel_uncore_topology *t;
+
+	for (idx = 0; idx < type->num_boxes; idx++) {
+		t = &type->topology[die][idx];
+		t->pmu_idx = idx;
+		t->iio->segment = segment;
+		t->iio->pci_bus_no = (cpu_bus_msr >> (idx * BUS_NUM_STRIDE)) & 0xff;
+	}
+
+	return 0;
+}
+
+static int skx_iio_get_topology(struct intel_uncore_type *type)
+{
+	return skx_pmu_get_topology(type, skx_iio_topology_cb);
+}
+
 static struct attribute_group skx_iio_mapping_group = {
 	.is_visible	= skx_iio_mapping_visible,
 };

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D
  2022-11-17 12:28 ` [PATCH 04/11] perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel),
	Kan Liang, stable, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     efe062705d149b20a15498cb999a9edbb8241e6f
Gitweb:        https://git.kernel.org/tip/efe062705d149b20a15498cb999a9edbb8241e6f
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:26 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:21 +01:00

perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D

Current implementation of I/O stacks to PMU mapping doesn't support ICX-D.
Detect ICX-D system to disable mapping.

Fixes: 10337e95e04c ("perf/x86/intel/uncore: Enable I/O stacks to IIO PMON mapping on ICX")
Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20221117122833.3103580-5-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore.h       | 1 +
 arch/x86/events/intel/uncore_snbep.c | 5 +++++
 2 files changed, 6 insertions(+)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index ef14149..fac3612 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -2,6 +2,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <asm/apicdef.h>
+#include <asm/intel-family.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 
 #include <linux/perf_event.h>
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 0d06b56..e14b963 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -5226,6 +5226,11 @@ static int icx_iio_get_topology(struct intel_uncore_type *type)
 
 static int icx_iio_set_mapping(struct intel_uncore_type *type)
 {
+	/* Detect ICX-D system. This case is not supported */
+	if (boot_cpu_data.x86_model == INTEL_FAM6_ICELAKE_D) {
+		pmu_clear_mapping_attr(type->attr_update, &icx_iio_mapping_group);
+		return -EPERM;
+	}
 	return pmu_iio_set_mapping(type, &icx_iio_mapping_group);
 }
 

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Clear attr_update properly
  2022-11-17 12:28 ` [PATCH 03/11] perf/x86/intel/uncore: Clear attr_update properly alexander.antonov
@ 2022-11-24 12:02   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:02 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel),
	Kan Liang, stable, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     6532783310e2b2f50dc13f46c49aa6546cb6e7a3
Gitweb:        https://git.kernel.org/tip/6532783310e2b2f50dc13f46c49aa6546cb6e7a3
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:25 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:20 +01:00

perf/x86/intel/uncore: Clear attr_update properly

Current clear_attr_update procedure in pmu_set_mapping() sets attr_update
field in NULL that is not correct because intel_uncore_type pmu types can
contain several groups in attr_update field. For example, SPR platform
already has uncore_alias_group to update and then UPI topology group will
be added in next patches.

Fix current behavior and clear attr_update group related to mapping only.

Fixes: bb42b3d39781 ("perf/x86/intel/uncore: Expose an Uncore unit to IIO PMON mapping")
Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20221117122833.3103580-4-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore_snbep.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index d3323f1..0d06b56 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3872,6 +3872,21 @@ static const struct attribute_group *skx_iio_attr_update[] = {
 	NULL,
 };
 
+static void pmu_clear_mapping_attr(const struct attribute_group **groups,
+				   struct attribute_group *ag)
+{
+	int i;
+
+	for (i = 0; groups[i]; i++) {
+		if (groups[i] == ag) {
+			for (i++; groups[i]; i++)
+				groups[i - 1] = groups[i];
+			groups[i - 1] = NULL;
+			break;
+		}
+	}
+}
+
 static int
 pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
 		ssize_t (*show)(struct device*, struct device_attribute*, char*),
@@ -3926,7 +3941,7 @@ clear_attrs:
 clear_topology:
 	pmu_free_topology(type);
 clear_attr_update:
-	type->attr_update = NULL;
+	pmu_clear_mapping_attr(type->attr_update, ag);
 	return ret;
 }
 

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Introduce UPI topology type
  2022-11-17 12:28 ` [PATCH 02/11] perf/x86/intel/uncore: Introduce UPI topology type alexander.antonov
@ 2022-11-24 12:03   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:03 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     cee4eebd9158d9eb3f8c1708c297b219e8ea861f
Gitweb:        https://git.kernel.org/tip/cee4eebd9158d9eb3f8c1708c297b219e8ea861f
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:24 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:20 +01:00

perf/x86/intel/uncore: Introduce UPI topology type

This patch introduces new 'uncore_upi_topology' topology type to support
UPI topology discovery.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-3-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore.h       | 7 +++++++
 arch/x86/events/intel/uncore_snbep.c | 4 +++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 917cff1..ef14149 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -183,11 +183,18 @@ struct uncore_iio_topology {
 	int segment;
 };
 
+struct uncore_upi_topology {
+	int die_to;
+	int pmu_idx_to;
+	int enabled;
+};
+
 struct intel_uncore_topology {
 	int pmu_idx;
 	union {
 		void *untyped;
 		struct uncore_iio_topology *iio;
+		struct uncore_upi_topology *upi;
 	};
 };
 
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 469ff88..d3323f1 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3774,11 +3774,13 @@ static int die_to_cpu(int die)
 
 enum {
 	IIO_TOPOLOGY_TYPE,
+	UPI_TOPOLOGY_TYPE,
 	TOPOLOGY_MAX
 };
 
 static const size_t topology_size[TOPOLOGY_MAX] = {
-	sizeof(*((struct intel_uncore_topology *)NULL)->iio)
+	sizeof(*((struct intel_uncore_topology *)NULL)->iio),
+	sizeof(*((struct intel_uncore_topology *)NULL)->upi)
 };
 
 static int pmu_alloc_topology(struct intel_uncore_type *type, int topology_type)

^ permalink raw reply related	[flat|nested] 23+ messages in thread

* [tip: perf/core] perf/x86/intel/uncore: Generalize IIO topology support
  2022-11-17 12:28 ` [PATCH 01/11] perf/x86/intel/uncore: Generalize IIO topology support alexander.antonov
@ 2022-11-24 12:03   ` tip-bot2 for Alexander Antonov
  0 siblings, 0 replies; 23+ messages in thread
From: tip-bot2 for Alexander Antonov @ 2022-11-24 12:03 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alexander Antonov, Peter Zijlstra (Intel), Kan Liang, x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     4d13be8ab5d4aa6106331baa9674632a75b884b0
Gitweb:        https://git.kernel.org/tip/4d13be8ab5d4aa6106331baa9674632a75b884b0
Author:        Alexander Antonov <alexander.antonov@linux.intel.com>
AuthorDate:    Thu, 17 Nov 2022 12:28:23 
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Thu, 24 Nov 2022 11:09:20 +01:00

perf/x86/intel/uncore: Generalize IIO topology support

Current implementation of uncore mapping doesn't support different types
of uncore PMUs which have its own topology context. This patch generalizes
Intel uncore topology implementation to be able easily introduce support
for new uncore blocks.

Signed-off-by: Alexander Antonov <alexander.antonov@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kan Liang <kan.liang@linux.intel.com>
Link: https://lore.kernel.org/r/20221117122833.3103580-2-alexander.antonov@linux.intel.com
---
 arch/x86/events/intel/uncore.h       |  14 +-
 arch/x86/events/intel/uncore_snbep.c | 152 ++++++++++++++++++--------
 2 files changed, 122 insertions(+), 44 deletions(-)

diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 2adeaf4..917cff1 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -88,7 +88,7 @@ struct intel_uncore_type {
 	 * to identify which platform component each PMON block of that type is
 	 * supposed to monitor.
 	 */
-	struct intel_uncore_topology *topology;
+	struct intel_uncore_topology **topology;
 	/*
 	 * Optional callbacks for managing mapping of Uncore units to PMONs
 	 */
@@ -178,11 +178,19 @@ struct freerunning_counters {
 	unsigned *box_offsets;
 };
 
-struct intel_uncore_topology {
-	u64 configuration;
+struct uncore_iio_topology {
+	int pci_bus_no;
 	int segment;
 };
 
+struct intel_uncore_topology {
+	int pmu_idx;
+	union {
+		void *untyped;
+		struct uncore_iio_topology *iio;
+	};
+};
+
 struct pci2phy_map {
 	struct list_head list;
 	int segment;
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index ed86944..469ff88 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -3699,10 +3699,16 @@ static struct intel_uncore_ops skx_uncore_iio_ops = {
 	.read_counter		= uncore_msr_read_counter,
 };
 
-static inline u8 skx_iio_stack(struct intel_uncore_pmu *pmu, int die)
+static struct intel_uncore_topology *pmu_topology(struct intel_uncore_pmu *pmu, int die)
 {
-	return pmu->type->topology[die].configuration >>
-	       (pmu->pmu_idx * BUS_NUM_STRIDE);
+	int idx;
+
+	for (idx = 0; idx < pmu->type->num_boxes; idx++) {
+		if (pmu->type->topology[die][idx].pmu_idx == pmu->pmu_idx)
+			return &pmu->type->topology[die][idx];
+	}
+
+	return NULL;
 }
 
 static umode_t
@@ -3710,8 +3716,9 @@ pmu_iio_mapping_visible(struct kobject *kobj, struct attribute *attr,
 			 int die, int zero_bus_pmu)
 {
 	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
+	struct intel_uncore_topology *pmut = pmu_topology(pmu, die);
 
-	return (!skx_iio_stack(pmu, die) && pmu->pmu_idx != zero_bus_pmu) ? 0 : attr->mode;
+	return (pmut && !pmut->iio->pci_bus_no && pmu->pmu_idx != zero_bus_pmu) ? 0 : attr->mode;
 }
 
 static umode_t
@@ -3727,9 +3734,10 @@ static ssize_t skx_iio_mapping_show(struct device *dev,
 	struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
 	struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
 	long die = (long)ea->var;
+	struct intel_uncore_topology *pmut = pmu_topology(pmu, die);
 
-	return sprintf(buf, "%04x:%02x\n", pmu->type->topology[die].segment,
-					   skx_iio_stack(pmu, die));
+	return sprintf(buf, "%04x:%02x\n", pmut ? pmut->iio->segment : 0,
+					   pmut ? pmut->iio->pci_bus_no : 0);
 }
 
 static int skx_msr_cpu_bus_read(int cpu, u64 *topology)
@@ -3764,18 +3772,77 @@ static int die_to_cpu(int die)
 	return res;
 }
 
+enum {
+	IIO_TOPOLOGY_TYPE,
+	TOPOLOGY_MAX
+};
+
+static const size_t topology_size[TOPOLOGY_MAX] = {
+	sizeof(*((struct intel_uncore_topology *)NULL)->iio)
+};
+
+static int pmu_alloc_topology(struct intel_uncore_type *type, int topology_type)
+{
+	int die, idx;
+	struct intel_uncore_topology **topology;
+
+	if (!type->num_boxes)
+		return -EPERM;
+
+	topology = kcalloc(uncore_max_dies(), sizeof(*topology), GFP_KERNEL);
+	if (!topology)
+		goto err;
+
+	for (die = 0; die < uncore_max_dies(); die++) {
+		topology[die] = kcalloc(type->num_boxes, sizeof(**topology), GFP_KERNEL);
+		if (!topology[die])
+			goto clear;
+		for (idx = 0; idx < type->num_boxes; idx++) {
+			topology[die][idx].untyped = kcalloc(type->num_boxes,
+							     topology_size[topology_type],
+							     GFP_KERNEL);
+			if (!topology[die][idx].untyped)
+				goto clear;
+		}
+	}
+
+	type->topology = topology;
+
+	return 0;
+clear:
+	for (; die >= 0; die--) {
+		for (idx = 0; idx < type->num_boxes; idx++)
+			kfree(topology[die][idx].untyped);
+		kfree(topology[die]);
+	}
+	kfree(topology);
+err:
+	return -ENOMEM;
+}
+
+static void pmu_free_topology(struct intel_uncore_type *type)
+{
+	int die, idx;
+
+	if (type->topology) {
+		for (die = 0; die < uncore_max_dies(); die++) {
+			for (idx = 0; idx < type->num_boxes; idx++)
+				kfree(type->topology[die][idx].untyped);
+			kfree(type->topology[die]);
+		}
+		kfree(type->topology);
+		type->topology = NULL;
+	}
+}
+
 static int skx_iio_get_topology(struct intel_uncore_type *type)
 {
 	int die, ret = -EPERM;
-
-	type->topology = kcalloc(uncore_max_dies(), sizeof(*type->topology),
-				 GFP_KERNEL);
-	if (!type->topology)
-		return -ENOMEM;
+	u64 configuration;
+	int idx;
 
 	for (die = 0; die < uncore_max_dies(); die++) {
-		ret = skx_msr_cpu_bus_read(die_to_cpu(die),
-					   &type->topology[die].configuration);
+		ret = skx_msr_cpu_bus_read(die_to_cpu(die), &configuration);
 		if (ret)
 			break;
 
@@ -3783,12 +3850,12 @@ static int skx_iio_get_topology(struct intel_uncore_type *type)
 		if (ret < 0)
 			break;
 
-		type->topology[die].segment = ret;
-	}
-
-	if (ret < 0) {
-		kfree(type->topology);
-		type->topology = NULL;
+		for (idx = 0; idx < type->num_boxes; idx++) {
+			type->topology[die][idx].pmu_idx = idx;
+			type->topology[die][idx].iio->segment = ret;
+			type->topology[die][idx].iio->pci_bus_no =
+				(configuration >> (idx * BUS_NUM_STRIDE)) & 0xff;
+		}
 	}
 
 	return ret;
@@ -3804,7 +3871,9 @@ static const struct attribute_group *skx_iio_attr_update[] = {
 };
 
 static int
-pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
+		ssize_t (*show)(struct device*, struct device_attribute*, char*),
+		int topology_type)
 {
 	char buf[64];
 	int ret;
@@ -3812,10 +3881,14 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 	struct attribute **attrs = NULL;
 	struct dev_ext_attribute *eas = NULL;
 
-	ret = type->get_topology(type);
+	ret = pmu_alloc_topology(type, topology_type);
 	if (ret < 0)
 		goto clear_attr_update;
 
+	ret = type->get_topology(type);
+	if (ret < 0)
+		goto clear_topology;
+
 	ret = -ENOMEM;
 
 	/* One more for NULL. */
@@ -3828,13 +3901,13 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 		goto clear_attrs;
 
 	for (die = 0; die < uncore_max_dies(); die++) {
-		sprintf(buf, "die%ld", die);
+		snprintf(buf, sizeof(buf), "die%ld", die);
 		sysfs_attr_init(&eas[die].attr.attr);
 		eas[die].attr.attr.name = kstrdup(buf, GFP_KERNEL);
 		if (!eas[die].attr.attr.name)
 			goto err;
 		eas[die].attr.attr.mode = 0444;
-		eas[die].attr.show = skx_iio_mapping_show;
+		eas[die].attr.show = show;
 		eas[die].attr.store = NULL;
 		eas[die].var = (void *)die;
 		attrs[die] = &eas[die].attr.attr;
@@ -3849,14 +3922,14 @@ err:
 clear_attrs:
 	kfree(attrs);
 clear_topology:
-	kfree(type->topology);
+	pmu_free_topology(type);
 clear_attr_update:
 	type->attr_update = NULL;
 	return ret;
 }
 
 static void
-pmu_iio_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+pmu_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
 {
 	struct attribute **attr = ag->attrs;
 
@@ -3868,7 +3941,13 @@ pmu_iio_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *
 	kfree(attr_to_ext_attr(*ag->attrs));
 	kfree(ag->attrs);
 	ag->attrs = NULL;
-	kfree(type->topology);
+	pmu_free_topology(type);
+}
+
+static int
+pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+{
+	return pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
 }
 
 static int skx_iio_set_mapping(struct intel_uncore_type *type)
@@ -3878,7 +3957,7 @@ static int skx_iio_set_mapping(struct intel_uncore_type *type)
 
 static void skx_iio_cleanup_mapping(struct intel_uncore_type *type)
 {
-	pmu_iio_cleanup_mapping(type, &skx_iio_mapping_group);
+	pmu_cleanup_mapping(type, &skx_iio_mapping_group);
 }
 
 static struct intel_uncore_type skx_uncore_iio = {
@@ -4461,11 +4540,6 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map
 	int die, stack_id, ret = -EPERM;
 	struct pci_dev *dev = NULL;
 
-	type->topology = kcalloc(uncore_max_dies(), sizeof(*type->topology),
-				 GFP_KERNEL);
-	if (!type->topology)
-		return -ENOMEM;
-
 	while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, SNR_ICX_MESH2IIO_MMAP_DID, dev))) {
 		ret = pci_read_config_dword(dev, SNR_ICX_SAD_CONTROL_CFG, &sad_cfg);
 		if (ret) {
@@ -4483,13 +4557,9 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map
 		/* Convert stack id from SAD_CONTROL to PMON notation. */
 		stack_id = sad_pmon_mapping[stack_id];
 
-		((u8 *)&(type->topology[die].configuration))[stack_id] = dev->bus->number;
-		type->topology[die].segment = pci_domain_nr(dev->bus);
-	}
-
-	if (ret) {
-		kfree(type->topology);
-		type->topology = NULL;
+		type->topology[die][stack_id].iio->segment = pci_domain_nr(dev->bus);
+		type->topology[die][stack_id].pmu_idx = stack_id;
+		type->topology[die][stack_id].iio->pci_bus_no = dev->bus->number;
 	}
 
 	return ret;
@@ -4526,7 +4596,7 @@ static int snr_iio_set_mapping(struct intel_uncore_type *type)
 
 static void snr_iio_cleanup_mapping(struct intel_uncore_type *type)
 {
-	pmu_iio_cleanup_mapping(type, &snr_iio_mapping_group);
+	pmu_cleanup_mapping(type, &snr_iio_mapping_group);
 }
 
 static struct event_constraint snr_uncore_iio_constraints[] = {
@@ -5144,7 +5214,7 @@ static int icx_iio_set_mapping(struct intel_uncore_type *type)
 
 static void icx_iio_cleanup_mapping(struct intel_uncore_type *type)
 {
-	pmu_iio_cleanup_mapping(type, &icx_iio_mapping_group);
+	pmu_cleanup_mapping(type, &icx_iio_mapping_group);
 }
 
 static struct intel_uncore_type icx_uncore_iio = {

^ permalink raw reply related	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2022-11-24 12:04 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-17 12:28 [PATCH 00/11] UPI topology discovery for SKX/ICX/SPR alexander.antonov
2022-11-17 12:28 ` [PATCH 01/11] perf/x86/intel/uncore: Generalize IIO topology support alexander.antonov
2022-11-24 12:03   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 02/11] perf/x86/intel/uncore: Introduce UPI topology type alexander.antonov
2022-11-24 12:03   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 03/11] perf/x86/intel/uncore: Clear attr_update properly alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 04/11] perf/x86/intel/uncore: Disable I/O stacks to PMU mapping on ICX-D alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 05/11] perf/x86/intel/uncore: Generalize get_topology() for SKX PMUs alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 06/11] perf/x86/intel/uncore: Enable UPI topology discovery for Skylake Server alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 07/11] perf/x86/intel/uncore: Get UPI NodeID and GroupID alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 08/11] perf/x86/intel/uncore: Enable UPI topology discovery for Icelake Server alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 09/11] perf/x86/intel/uncore: Enable UPI topology discovery for Sapphire Rapids alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 10/11] perf/x86/intel/uncore: Update sysfs-devices-mapping file alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov
2022-11-17 12:28 ` [PATCH 11/11] perf/x86/intel/uncore: Make set_mapping() procedure void alexander.antonov
2022-11-24 12:02   ` [tip: perf/core] " tip-bot2 for Alexander Antonov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).