From a2e702a2f3ffb9c90263285d333a2107cfb43fc4 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Wed, 14 Feb 2018 10:00:06 +0000 Subject: Factor out CPU AMU helpers This patch also fixes `cpuamu_write_cpuamcntenclr_el0()` to use an MSR instruction instead of an MRS instruction. Change-Id: Ia6531f64b5ebc60ba432124eaa8d8eaccba40ed0 Signed-off-by: Dimitris Papastamos --- lib/cpus/aarch64/cpuamu_helpers.S | 107 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 lib/cpus/aarch64/cpuamu_helpers.S (limited to 'lib') diff --git a/lib/cpus/aarch64/cpuamu_helpers.S b/lib/cpus/aarch64/cpuamu_helpers.S new file mode 100644 index 000000000..8965d6d09 --- /dev/null +++ b/lib/cpus/aarch64/cpuamu_helpers.S @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl cpuamu_cnt_read + .globl cpuamu_cnt_write + .globl cpuamu_read_cpuamcntenset_el0 + .globl cpuamu_read_cpuamcntenclr_el0 + .globl cpuamu_write_cpuamcntenset_el0 + .globl cpuamu_write_cpuamcntenclr_el0 + +/* + * uint64_t cpuamu_cnt_read(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func cpuamu_cnt_read + adr x1, 1f + lsl x0, x0, #3 + add x1, x1, x0 + br x1 + +1: + mrs x0, CPUAMEVCNTR0_EL0 + ret + mrs x0, CPUAMEVCNTR1_EL0 + ret + mrs x0, CPUAMEVCNTR2_EL0 + ret + mrs x0, CPUAMEVCNTR3_EL0 + ret + mrs x0, CPUAMEVCNTR4_EL0 + ret +endfunc cpuamu_cnt_read + +/* + * void cpuamu_cnt_write(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func cpuamu_cnt_write + adr x2, 1f + lsl x0, x0, #3 + add x2, x2, x0 + br x2 + +1: + msr CPUAMEVCNTR0_EL0, x0 + ret + msr CPUAMEVCNTR1_EL0, x0 + ret + msr CPUAMEVCNTR2_EL0, x0 + ret + msr CPUAMEVCNTR3_EL0, x0 + ret + msr CPUAMEVCNTR4_EL0, x0 + ret +endfunc cpuamu_cnt_write + +/* + * unsigned int cpuamu_read_cpuamcntenset_el0(void); + * + * Read the `CPUAMCNTENSET_EL0` CPU register and return + * it in `x0`. + */ +func cpuamu_read_cpuamcntenset_el0 + mrs x0, CPUAMCNTENSET_EL0 + ret +endfunc cpuamu_read_cpuamcntenset_el0 + +/* + * unsigned int cpuamu_read_cpuamcntenclr_el0(void); + * + * Read the `CPUAMCNTENCLR_EL0` CPU register and return + * it in `x0`. + */ +func cpuamu_read_cpuamcntenclr_el0 + mrs x0, CPUAMCNTENCLR_EL0 + ret +endfunc cpuamu_read_cpuamcntenclr_el0 + +/* + * void cpuamu_write_cpuamcntenset_el0(unsigned int mask); + * + * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register. + */ +func cpuamu_write_cpuamcntenset_el0 + msr CPUAMCNTENSET_EL0, x0 + ret +endfunc cpuamu_write_cpuamcntenset_el0 + +/* + * void cpuamu_write_cpuamcntenclr_el0(unsigned int mask); + * + * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register. + */ +func cpuamu_write_cpuamcntenclr_el0 + msr CPUAMCNTENCLR_EL0, x0 + ret +endfunc cpuamu_write_cpuamcntenclr_el0 -- cgit v1.2.3 From f06890ea89f6c20f5d4619ba3d108c43d5d89b18 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Wed, 14 Feb 2018 10:28:36 +0000 Subject: Refactor AMU support for Cortex A75 This patch also fixes the assumption that the counters are disabled on the resume path. This is incorrect as the AMU counters are enabled early in the CPU reset function before `cpuamu_context_restore()` runs. Change-Id: I38a94eb166a523f00de18e86860434ffccff2131 Signed-off-by: Dimitris Papastamos --- lib/cpus/aarch64/cortex_a75.S | 103 +---------------------------------- lib/cpus/aarch64/cortex_a75_pubsub.c | 61 ++------------------- lib/cpus/aarch64/cpuamu.c | 70 ++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 156 deletions(-) create mode 100644 lib/cpus/aarch64/cpuamu.c (limited to 'lib') diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S index 946f98843..12ea304d0 100644 --- a/lib/cpus/aarch64/cortex_a75.S +++ b/lib/cpus/aarch64/cortex_a75.S @@ -6,108 +6,9 @@ #include #include -#include -#include -#include #include - - .globl cortex_a75_amu_cnt_read - .globl cortex_a75_amu_cnt_write - .globl cortex_a75_amu_read_cpuamcntenset_el0 - .globl cortex_a75_amu_read_cpuamcntenclr_el0 - .globl cortex_a75_amu_write_cpuamcntenset_el0 - .globl cortex_a75_amu_write_cpuamcntenclr_el0 - -/* - * uint64_t cortex_a75_amu_cnt_read(int idx); - * - * Given `idx`, read the corresponding AMU counter - * and return it in `x0`. - */ -func cortex_a75_amu_cnt_read - adr x1, 1f - lsl x0, x0, #3 - add x1, x1, x0 - br x1 - -1: - mrs x0, CPUAMEVCNTR0_EL0 - ret - mrs x0, CPUAMEVCNTR1_EL0 - ret - mrs x0, CPUAMEVCNTR2_EL0 - ret - mrs x0, CPUAMEVCNTR3_EL0 - ret - mrs x0, CPUAMEVCNTR4_EL0 - ret -endfunc cortex_a75_amu_cnt_read - -/* - * void cortex_a75_amu_cnt_write(int idx, uint64_t val); - * - * Given `idx`, write `val` to the corresponding AMU counter. - */ -func cortex_a75_amu_cnt_write - adr x2, 1f - lsl x0, x0, #3 - add x2, x2, x0 - br x2 - -1: - msr CPUAMEVCNTR0_EL0, x0 - ret - msr CPUAMEVCNTR1_EL0, x0 - ret - msr CPUAMEVCNTR2_EL0, x0 - ret - msr CPUAMEVCNTR3_EL0, x0 - ret - msr CPUAMEVCNTR4_EL0, x0 - ret -endfunc cortex_a75_amu_cnt_write - -/* - * unsigned int cortex_a75_amu_read_cpuamcntenset_el0(void); - * - * Read the `CPUAMCNTENSET_EL0` CPU register and return - * it in `x0`. - */ -func cortex_a75_amu_read_cpuamcntenset_el0 - mrs x0, CPUAMCNTENSET_EL0 - ret -endfunc cortex_a75_amu_read_cpuamcntenset_el0 - -/* - * unsigned int cortex_a75_amu_read_cpuamcntenclr_el0(void); - * - * Read the `CPUAMCNTENCLR_EL0` CPU register and return - * it in `x0`. - */ -func cortex_a75_amu_read_cpuamcntenclr_el0 - mrs x0, CPUAMCNTENCLR_EL0 - ret -endfunc cortex_a75_amu_read_cpuamcntenclr_el0 - -/* - * void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask); - * - * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register. - */ -func cortex_a75_amu_write_cpuamcntenset_el0 - msr CPUAMCNTENSET_EL0, x0 - ret -endfunc cortex_a75_amu_write_cpuamcntenset_el0 - -/* - * void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask); - * - * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register. - */ -func cortex_a75_amu_write_cpuamcntenclr_el0 - mrs x0, CPUAMCNTENCLR_EL0 - ret -endfunc cortex_a75_amu_write_cpuamcntenclr_el0 +#include +#include func cortex_a75_reset_func #if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c index a1ffcb041..87beca273 100644 --- a/lib/cpus/aarch64/cortex_a75_pubsub.c +++ b/lib/cpus/aarch64/cortex_a75_pubsub.c @@ -1,73 +1,24 @@ /* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include -#include +#include #include -struct amu_ctx { - uint64_t cnts[CORTEX_A75_AMU_NR_COUNTERS]; - uint16_t mask; -}; - -static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; - static void *cortex_a75_context_save(const void *arg) { - struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; - unsigned int midr; - unsigned int midr_mask; - int i; - - midr = read_midr(); - midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | - (MIDR_PN_MASK << MIDR_PN_SHIFT); - if ((midr & midr_mask) != (CORTEX_A75_MIDR & midr_mask)) - return 0; - - /* Save counter configuration */ - ctx->mask = cortex_a75_amu_read_cpuamcntenset_el0(); - - /* Ensure counters are disabled */ - cortex_a75_amu_write_cpuamcntenclr_el0(ctx->mask); - isb(); - - /* Save counters */ - for (i = 0; i < CORTEX_A75_AMU_NR_COUNTERS; i++) - ctx->cnts[i] = cortex_a75_amu_cnt_read(i); - + if (midr_match(CORTEX_A75_MIDR)) + cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS); return 0; } static void *cortex_a75_context_restore(const void *arg) { - struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; - unsigned int midr; - unsigned int midr_mask; - int i; - - midr = read_midr(); - midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | - (MIDR_PN_MASK << MIDR_PN_SHIFT); - if ((midr & midr_mask) != (CORTEX_A75_MIDR & midr_mask)) - return 0; - - ctx = &amu_ctxs[plat_my_core_pos()]; - - /* Counters were disabled in `cortex_a75_context_save()` */ - assert(cortex_a75_amu_read_cpuamcntenset_el0() == 0); - - /* Restore counters */ - for (i = 0; i < CORTEX_A75_AMU_NR_COUNTERS; i++) - cortex_a75_amu_cnt_write(i, ctx->cnts[i]); - isb(); - - /* Restore counter configuration */ - cortex_a75_amu_write_cpuamcntenset_el0(ctx->mask); - + if (midr_match(CORTEX_A75_MIDR)) + cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS); return 0; } diff --git a/lib/cpus/aarch64/cpuamu.c b/lib/cpus/aarch64/cpuamu.c new file mode 100644 index 000000000..38c093ac4 --- /dev/null +++ b/lib/cpus/aarch64/cpuamu.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define CPUAMU_NR_COUNTERS 5 + +struct amu_ctx { + uint64_t cnts[CPUAMU_NR_COUNTERS]; + uint16_t mask; +}; + +static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; + +int midr_match(unsigned int cpu_midr) +{ + unsigned int midr, midr_mask; + + midr = read_midr(); + midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | + (MIDR_PN_MASK << MIDR_PN_SHIFT); + return ((midr & midr_mask) == (cpu_midr & midr_mask)); +} + +void cpuamu_context_save(unsigned int nr_counters) +{ + struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; + int i; + + assert(nr_counters <= CPUAMU_NR_COUNTERS); + + /* Save counter configuration */ + ctx->mask = cpuamu_read_cpuamcntenset_el0(); + + /* Disable counters */ + cpuamu_write_cpuamcntenclr_el0(ctx->mask); + isb(); + + /* Save counters */ + for (i = 0; i < nr_counters; i++) + ctx->cnts[i] = cpuamu_cnt_read(i); +} + +void cpuamu_context_restore(unsigned int nr_counters) +{ + struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; + int i; + + assert(nr_counters <= CPUAMU_NR_COUNTERS); + + /* + * Disable counters. They were enabled early in the + * CPU reset function. + */ + cpuamu_write_cpuamcntenclr_el0(ctx->mask); + isb(); + + /* Restore counters */ + for (i = 0; i < nr_counters; i++) + cpuamu_cnt_write(i, ctx->cnts[i]); + isb(); + + /* Restore counter configuration */ + cpuamu_write_cpuamcntenset_el0(ctx->mask); +} -- cgit v1.2.3 From 714b21ffc71170bba343589fc010001645f1db57 Mon Sep 17 00:00:00 2001 From: Dimitris Papastamos Date: Tue, 27 Feb 2018 10:55:39 +0000 Subject: MISRA fixes for Cortex A75 AMU implementation Change-Id: I61c9fdfda0c0b3c3ec6249519db23602cf4c2100 Signed-off-by: Dimitris Papastamos --- lib/cpus/aarch64/cortex_a75_pubsub.c | 4 ++-- lib/cpus/aarch64/cpuamu.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/cpus/aarch64/cortex_a75_pubsub.c b/lib/cpus/aarch64/cortex_a75_pubsub.c index 87beca273..16f62f472 100644 --- a/lib/cpus/aarch64/cortex_a75_pubsub.c +++ b/lib/cpus/aarch64/cortex_a75_pubsub.c @@ -10,14 +10,14 @@ static void *cortex_a75_context_save(const void *arg) { - if (midr_match(CORTEX_A75_MIDR)) + if (midr_match(CORTEX_A75_MIDR) != 0) cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS); return 0; } static void *cortex_a75_context_restore(const void *arg) { - if (midr_match(CORTEX_A75_MIDR)) + if (midr_match(CORTEX_A75_MIDR) != 0) cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS); return 0; } diff --git a/lib/cpus/aarch64/cpuamu.c b/lib/cpus/aarch64/cpuamu.c index 38c093ac4..b9bad8604 100644 --- a/lib/cpus/aarch64/cpuamu.c +++ b/lib/cpus/aarch64/cpuamu.c @@ -8,11 +8,11 @@ #include #include -#define CPUAMU_NR_COUNTERS 5 +#define CPUAMU_NR_COUNTERS 5U struct amu_ctx { uint64_t cnts[CPUAMU_NR_COUNTERS]; - uint16_t mask; + unsigned int mask; }; static struct amu_ctx amu_ctxs[PLATFORM_CORE_COUNT]; @@ -21,7 +21,7 @@ int midr_match(unsigned int cpu_midr) { unsigned int midr, midr_mask; - midr = read_midr(); + midr = (unsigned int)read_midr(); midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | (MIDR_PN_MASK << MIDR_PN_SHIFT); return ((midr & midr_mask) == (cpu_midr & midr_mask)); @@ -30,7 +30,7 @@ int midr_match(unsigned int cpu_midr) void cpuamu_context_save(unsigned int nr_counters) { struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; - int i; + unsigned int i; assert(nr_counters <= CPUAMU_NR_COUNTERS); @@ -49,7 +49,7 @@ void cpuamu_context_save(unsigned int nr_counters) void cpuamu_context_restore(unsigned int nr_counters) { struct amu_ctx *ctx = &amu_ctxs[plat_my_core_pos()]; - int i; + unsigned int i; assert(nr_counters <= CPUAMU_NR_COUNTERS); -- cgit v1.2.3