mbox series

[v5,0/4] arm64: SPE ACPI enablement

Message ID 20190626213718.39423-1-jeremy.linton@arm.com
Headers show
Series arm64: SPE ACPI enablement | expand

Message

Jeremy Linton June 26, 2019, 9:37 p.m. UTC
This patch series enables the Arm Statistical Profiling
Extension (SPE) on ACPI platforms.

This is possible because ACPI 6.3 uses a previously
reserved field in the MADT to store the SPE interrupt
number, similarly to how the normal PMU is described.
If a consistent valid interrupt exists across all the
cores in the system, a platform device is registered.
That then triggers the SPE module, which runs as normal.

We also add the ability to parse the PPTT for IDENTICAL
cores. We then use this to sanity check the single SPE
device we create. This creates a bit of a problem with
respect to the specification though. The specification
says that its legal for multiple tree's to exist in the
PPTT. We handle this fine, but what happens in the
case of multiple tree's is that the lack of a common
node with IDENTICAL set forces us to assume that there
are multiple non-IDENTICAL cores in the machine.

v4->v5: Remove error returns from arm_spe_acpi_register_device()
	Add some review/test tags

v3->v4: Rebase to 5.2.
	Minor formatting, patch rearrangement.
	Add missing `inline` in static header definition.
	Drop ARM_SPE_ACPI and just use ARM_SPE_PMU.

v2->v3: Previously a function pointer was being used
	  to handle the more complex node checking
	  required by the IDENTICAL flag. This version
	  simply checks for the IDENTICAL flag and calls
	  flag_identical() to preform the revision
	  and next node checks. (I think after reading
	  Raphael's comments for the Nth time, this is
	  actually what he was suggesting, which I
	  initially miss interpreted).
	Modify subject of first patch so that its clear
	  a that its a capitalization change rather,
	  than a logical C 'case' change.

v1->v2: Wrap the code which creates the SPE device in
	    a new CONFIG_ARM_SPE_ACPI ifdef.
	Move arm,spe-v1 device name into common header file
	Some comment/case sensitivity/function name changes.

Jeremy Linton (4):
  ACPI/PPTT: Modify node flag detection to find last IDENTICAL
  ACPI/PPTT: Add function to return ACPI 6.3 Identical tokens
  arm_pmu: acpi: spe: Add initial MADT/SPE probing
  perf: arm_spe: Enable ACPI/Platform automatic module loading

 arch/arm64/include/asm/acpi.h |  3 ++
 drivers/acpi/pptt.c           | 61 ++++++++++++++++++++++++++---
 drivers/perf/arm_pmu_acpi.c   | 72 +++++++++++++++++++++++++++++++++++
 drivers/perf/arm_spe_pmu.c    | 12 +++++-
 include/linux/acpi.h          |  5 +++
 include/linux/perf/arm_pmu.h  |  2 +
 6 files changed, 147 insertions(+), 8 deletions(-)

-- 
2.21.0

Comments

Rafael J. Wysocki June 27, 2019, 11:15 a.m. UTC | #1
On Wed, Jun 26, 2019 at 11:37 PM Jeremy Linton <jeremy.linton@arm.com> wrote:
>

> The ACPI specification implies that the IDENTICAL flag should be

> set on all non leaf nodes where the children are identical.

> This means that we need to be searching for the last node with

> the identical flag set rather than the first one.

>

> Since this flag is also dependent on the table revision, we

> need to add a bit of extra code to verify the table revision,

> and the next node's state in the traversal. Since we want to

> avoid function pointers here, lets just special case

> the IDENTICAL flag.

>

> Tested-by: Hanjun Gou <gouhanjun@huawei.com>

> Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>

> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>


Assuming that the Tested-by tag will be fixed:

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>


> ---

>  drivers/acpi/pptt.c | 35 +++++++++++++++++++++++++++++------

>  1 file changed, 29 insertions(+), 6 deletions(-)

>

> diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c

> index b72e6afaa8fb..05344413f199 100644

> --- a/drivers/acpi/pptt.c

> +++ b/drivers/acpi/pptt.c

> @@ -432,17 +432,40 @@ static void cache_setup_acpi_cpu(struct acpi_table_header *table,

>         }

>  }

>

> +static bool flag_identical(struct acpi_table_header *table_hdr,

> +                          struct acpi_pptt_processor *cpu)

> +{

> +       struct acpi_pptt_processor *next;

> +

> +       /* heterogeneous machines must use PPTT revision > 1 */

> +       if (table_hdr->revision < 2)

> +               return false;

> +

> +       /* Locate the last node in the tree with IDENTICAL set */

> +       if (cpu->flags & ACPI_PPTT_ACPI_IDENTICAL) {

> +               next = fetch_pptt_node(table_hdr, cpu->parent);

> +               if (!(next && next->flags & ACPI_PPTT_ACPI_IDENTICAL))

> +                       return true;

> +       }

> +

> +       return false;

> +}

> +

>  /* Passing level values greater than this will result in search termination */

>  #define PPTT_ABORT_PACKAGE 0xFF

>

> -static struct acpi_pptt_processor *acpi_find_processor_package_id(struct acpi_table_header *table_hdr,

> -                                                                 struct acpi_pptt_processor *cpu,

> -                                                                 int level, int flag)

> +static struct acpi_pptt_processor *acpi_find_processor_tag(struct acpi_table_header *table_hdr,

> +                                                          struct acpi_pptt_processor *cpu,

> +                                                          int level, int flag)

>  {

>         struct acpi_pptt_processor *prev_node;

>

>         while (cpu && level) {

> -               if (cpu->flags & flag)

> +               /* special case the identical flag to find last identical */

> +               if (flag == ACPI_PPTT_ACPI_IDENTICAL) {

> +                       if (flag_identical(table_hdr, cpu))

> +                               break;

> +               } else if (cpu->flags & flag)

>                         break;

>                 pr_debug("level %d\n", level);

>                 prev_node = fetch_pptt_node(table_hdr, cpu->parent);

> @@ -480,8 +503,8 @@ static int topology_get_acpi_cpu_tag(struct acpi_table_header *table,

>

>         cpu_node = acpi_find_processor_node(table, acpi_cpu_id);

>         if (cpu_node) {

> -               cpu_node = acpi_find_processor_package_id(table, cpu_node,

> -                                                         level, flag);

> +               cpu_node = acpi_find_processor_tag(table, cpu_node,

> +                                                  level, flag);

>                 /*

>                  * As per specification if the processor structure represents

>                  * an actual processor, then ACPI processor ID must be valid.

> --

> 2.21.0

>
Will Deacon June 27, 2019, 4:47 p.m. UTC | #2
On Wed, Jun 26, 2019 at 04:37:14PM -0500, Jeremy Linton wrote:
> This patch series enables the Arm Statistical Profiling

> Extension (SPE) on ACPI platforms.

> 

> This is possible because ACPI 6.3 uses a previously

> reserved field in the MADT to store the SPE interrupt

> number, similarly to how the normal PMU is described.

> If a consistent valid interrupt exists across all the

> cores in the system, a platform device is registered.

> That then triggers the SPE module, which runs as normal.

> 

> We also add the ability to parse the PPTT for IDENTICAL

> cores. We then use this to sanity check the single SPE

> device we create. This creates a bit of a problem with

> respect to the specification though. The specification

> says that its legal for multiple tree's to exist in the

> PPTT. We handle this fine, but what happens in the

> case of multiple tree's is that the lack of a common

> node with IDENTICAL set forces us to assume that there

> are multiple non-IDENTICAL cores in the machine.

> 

> v4->v5: Remove error returns from arm_spe_acpi_register_device()

> 	Add some review/test tags


Cheers, I've pushed this out with the acks and typo fixes.

https://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git/log/?h=for-next/perf

Please let me know if you spot any problems.

Will