[01/10] perf/x86/intel: Introduce a concept "domain" as the scope of counters
diff mbox series

Message ID 1550606411-5313-2-git-send-email-kan.liang@linux.intel.com
State New
Headers show
Series
  • perf: Multi-die/package support
Related show

Commit Message

Liang, Kan Feb. 19, 2019, 8 p.m. UTC
From: Kan Liang <kan.liang@linux.intel.com>

Perf supports miscellaneous modules, e.g cstate, RAPL and uncore.
The counters of these modules have different scope of effect than core.
So these modules maintain their own scope information independently.
Actually, the scope of counters among these modules are similar.
It's very useful to abstract several common topology related codes for
these modules to reduce the code redundancy.
Furthermore, it will be very helpful if some counters within a new
scope are added, e.g die scope counters on CLX-AP. The similar topology
codes will not to be updated for each modules repeatedly.

A concept, "domain", is introduced as the scope of counters.
 - Domain type: A type of domain is classified by the scope of effect.
   Currently, there are two types of domain, PACKAGE_DOMAIN and
   CORE_DOMAIN. Their scope are physical package and physical core
   respectively.
   Add a new struct domain_type for domain type.
 - The number of domain for each type depends on the topology of the
   machine. For example, for a 4 socket machine, the number of domain
   is 4 for PACKAGE_DOMAIN type.
 - The domain ID: Each domain has an ID, which has to be consecutive.

Four common functions are abstracted.
 - domain_type_init(): Initialize domain type. Updates the number of
   domain for a given type. For PACKAGE_DOMAIN type, it's the maximum
   packages of the machine.
   Assign a postfix string for the name of a given domain type. If there
   are more than two types of domain on a system, the postfix is
   required to distinguish between domain types. For example, cstate PMU
   names are cstate_core and cstate_pkg. If there is only one type on a
   system, postfix is not applied, e.g. RAPL PMU name is powerf.
 - get_domain_cpu_mask(): Return a CPU mask for a given domain type and
   a CPU.
 - get_domain_id(): Return a domain ID for a given domain type and a
   CPU.
   Now, it is only used by RAPL and uncore for PACKAGE_DOMAIN type of
   domain. The domain ID is the same as the logical package ID.
 - get_domain_id_from_group_id(): Return a domain ID for a given domain
   type and a group ID of PCI BUS.
   The function is used by PCI uncore blocks to calculate the mapping
   between a domain ID and PCI BUS.
   For PACKAGE_DOMAIN type of domain, the group ID is the same as the
   physical package ID.

The new concept will be applied for each modules in the following
patches.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/Makefile |  2 +-
 arch/x86/events/domain.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
 arch/x86/events/domain.h | 25 +++++++++++++++++
 3 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/events/domain.c
 create mode 100644 arch/x86/events/domain.h

Comments

Peter Zijlstra Feb. 20, 2019, 11:12 a.m. UTC | #1
On Tue, Feb 19, 2019 at 12:00:02PM -0800, kan.liang@linux.intel.com wrote:
> It's very useful to abstract several common topology related codes for
> these modules to reduce the code redundancy.

>  3 files changed, 96 insertions(+), 1 deletion(-)

So you add 100 lines, so we can remove lines when we start to use this.

Except all 3 follow up patches that employ this, all add more lines
still:

 1 file changed, 184 insertions(+), 157 deletions(-)
 3 files changed, 164 insertions(+), 80 deletions(-)
 1 file changed, 224 insertions(+), 82 deletions(-)
Liang, Kan Feb. 20, 2019, 2:36 p.m. UTC | #2
On 2/20/2019 6:12 AM, Peter Zijlstra wrote:
> On Tue, Feb 19, 2019 at 12:00:02PM -0800, kan.liang@linux.intel.com wrote:
>> It's very useful to abstract several common topology related codes for
>> these modules to reduce the code redundancy.
> 
>>   3 files changed, 96 insertions(+), 1 deletion(-)
> 
> So you add 100 lines, so we can remove lines when we start to use this.
> 
> Except all 3 follow up patches that employ this, all add more lines
> still:

The previous implementation assumes that there is only one or two types 
of counters (per core or per package). The proposed solution breaks the 
assumption and can support more types of counters. The new 
infrastructure needs more lines. But with more and more types 
introduced, we can expect less lines in total with the proposed solution.

>   1 file changed, 184 insertions(+), 157 deletions(-)

This is cstate which supports two types of counters (per core and per 
package) now.

>   3 files changed, 164 insertions(+), 80 deletions(-)
>   1 file changed, 224 insertions(+), 82 deletions(-)
> 

They are uncore and rapl which only supports one type of counters (per 
package) now.

When there is only one type, the proposed solution has more lines.
But when there are two types, the proposed solution has similar number 
of lines as previous implementation.
In this trend, I expect that the proposed solution has less lines when 
there are three or more types.

With die introduced, there are at least two types of counters for rapl 
and uncore, and three types for cstate. In total, we should see less lines.

There may be more types of counters added later. In 8.9.1 Hierarchical 
Mapping of Shared Resources of SDM vol3A, it document 7 APIC_ID fields 
(cluster, package, die, tile, module, core and SMT). There are only 4 
types of counters for now.


Thanks,
Kan
Liang, Kan March 5, 2019, 8:32 p.m. UTC | #3
Hi Peter,

Is the idea (abstract common topology related codes for perf modules) 
the right direction?
I'm asking because I'm going to submit uncore codes for new platforms. 
I'm not sure if the new code should base on this series.

Could you please share your opinion?

If it's the right direction, could you please review the patch 1-4?
They are for previous platforms and can be merged separately.

If it's not the right time to do the abstraction, I will re-write the 
patches to only specially handle CLX-AP for now. For example, per-die 
counters can share the code with per-package counters by introducing a 
new variable 'bool die_scope' and checking the variable before calling 
any topology related functions.
But that's only a temporary solution for CLX-AP. We still need to add 
dedicated per-die PMU support later, if both per-die and per-package 
counters are supported on the same platforms.

Thanks,
Kan

On 2/20/2019 9:36 AM, Liang, Kan wrote:
> 
> 
> On 2/20/2019 6:12 AM, Peter Zijlstra wrote:
>> On Tue, Feb 19, 2019 at 12:00:02PM -0800, kan.liang@linux.intel.com 
>> wrote:
>>> It's very useful to abstract several common topology related codes for
>>> these modules to reduce the code redundancy.
>>
>>>   3 files changed, 96 insertions(+), 1 deletion(-)
>>
>> So you add 100 lines, so we can remove lines when we start to use this.
>>
>> Except all 3 follow up patches that employ this, all add more lines
>> still:
> 
> The previous implementation assumes that there is only one or two types 
> of counters (per core or per package). The proposed solution breaks the 
> assumption and can support more types of counters. The new 
> infrastructure needs more lines. But with more and more types 
> introduced, we can expect less lines in total with the proposed solution.
> 
>>   1 file changed, 184 insertions(+), 157 deletions(-)
> 
> This is cstate which supports two types of counters (per core and per 
> package) now.
> 
>>   3 files changed, 164 insertions(+), 80 deletions(-)
>>   1 file changed, 224 insertions(+), 82 deletions(-)
>>
> 
> They are uncore and rapl which only supports one type of counters (per 
> package) now.
> 
> When there is only one type, the proposed solution has more lines.
> But when there are two types, the proposed solution has similar number 
> of lines as previous implementation.
> In this trend, I expect that the proposed solution has less lines when 
> there are three or more types.
> 
> With die introduced, there are at least two types of counters for rapl 
> and uncore, and three types for cstate. In total, we should see less lines.
> 
> There may be more types of counters added later. In 8.9.1 Hierarchical 
> Mapping of Shared Resources of SDM vol3A, it document 7 APIC_ID fields 
> (cluster, package, die, tile, module, core and SMT). There are only 4 
> types of counters for now.
> 
> 
> Thanks,
> Kan

Patch
diff mbox series

diff --git a/arch/x86/events/Makefile b/arch/x86/events/Makefile
index b8ccdb5..db638e2 100644
--- a/arch/x86/events/Makefile
+++ b/arch/x86/events/Makefile
@@ -1,4 +1,4 @@ 
-obj-y					+= core.o
+obj-y					+= core.o domain.o
 obj-y					+= amd/
 obj-$(CONFIG_X86_LOCAL_APIC)            += msr.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/
diff --git a/arch/x86/events/domain.c b/arch/x86/events/domain.c
new file mode 100644
index 0000000..bd24c5b
--- /dev/null
+++ b/arch/x86/events/domain.c
@@ -0,0 +1,70 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019, Intel Corporation.
+ * Define "domain" as the scope of counters
+ *
+ */
+
+#include "domain.h"
+
+int domain_type_init(struct domain_type *type)
+{
+	switch (type->type) {
+	case PACKAGE_DOMAIN:
+		type->max_domains = topology_max_packages();
+		type->postfix = "pkg";
+		return 0;
+	case CORE_DOMAIN:
+		type->postfix = "core";
+		return 0;
+	default:
+		return -1;
+	}
+}
+EXPORT_SYMBOL_GPL(domain_type_init);
+
+/* Return a CPU mask for a given domain type and a CPU. */
+const struct cpumask *get_domain_cpu_mask(int cpu, struct domain_type *type)
+{
+	switch (type->type) {
+	case PACKAGE_DOMAIN:
+		return topology_die_cpumask(cpu);
+	case CORE_DOMAIN:
+		return topology_sibling_cpumask(cpu);
+	default:
+		return NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(get_domain_cpu_mask);
+
+/*
+ * Return a domain ID for a given domain type and a CPU.
+ * The domain ID has to be consecutive.
+ */
+int get_domain_id(unsigned int cpu, struct domain_type *type)
+{
+	switch (type->type) {
+	case PACKAGE_DOMAIN:
+		/* Domain id is the same as logical package id */
+		return topology_logical_package_id(cpu);
+	default:
+		return -1;
+	}
+}
+EXPORT_SYMBOL_GPL(get_domain_id);
+
+/*
+ * Return a domain ID for a given domain type and a group ID of PCI BUS.
+ * Used by uncore to calculate the mapping between a domain ID and PCI BUS.
+ */
+int get_domain_id_from_group_id(int id, struct domain_type *type)
+{
+	switch (type->type) {
+	case PACKAGE_DOMAIN:
+		/* group id is physical pkg id*/
+		return topology_phys_to_logical_pkg(id);
+	default:
+		return -1;
+	}
+}
+EXPORT_SYMBOL_GPL(get_domain_id_from_group_id);
diff --git a/arch/x86/events/domain.h b/arch/x86/events/domain.h
new file mode 100644
index 0000000..c787816
--- /dev/null
+++ b/arch/x86/events/domain.h
@@ -0,0 +1,25 @@ 
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2019, Intel Corporation.
+ */
+#include <linux/perf_event.h>
+
+#define DOMAIN_NAME_LEN	32
+
+enum domain_types {
+	PACKAGE_DOMAIN = 0,
+	CORE_DOMAIN,
+
+	DOMAIN_TYPE_MAX,
+};
+
+struct domain_type {
+	enum domain_types	type;
+	unsigned int		max_domains;
+	const char		*postfix;
+};
+
+int domain_type_init(struct domain_type *type);
+const struct cpumask *get_domain_cpu_mask(int cpu, struct domain_type *type);
+int get_domain_id(unsigned int cpu, struct domain_type *type);
+int get_domain_id_from_group_id(int id, struct domain_type *type);