* [PATCH v2] ARM: perf: reset counters on all CPUs during initialisation
@ 2011-03-23 15:46 Will Deacon
2011-03-24 16:22 ` Will Deacon
[not found] ` <-978680943347076223@unknownmsgid>
0 siblings, 2 replies; 3+ messages in thread
From: Will Deacon @ 2011-03-23 15:46 UTC (permalink / raw)
To: linux-arm-kernel
ARMv7 dictates that the interrupt-enable and count-enable registers for
each PMU counter are UNKNOWN following core reset.
This patch adds a new (optional) function pointer to struct arm_pmu for
resetting the PMU state during init. The reset function is called on
each CPU via an arch_initcall in the generic ARM perf_event code and
allows the PMU backend to write sane values to any UNKNOWN registers.
Cc: Jean Pihet <jean.pihet@ti.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
Hi Jean, here's the updated patch following the discussion on the list.
Please let me know what you think.
Will
arch/arm/kernel/perf_event.c | 14 ++++++++++++++
arch/arm/kernel/perf_event_v7.c | 22 ++++++++++++++++------
2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 53f6068..b23a364 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -79,6 +79,7 @@ struct arm_pmu {
void (*write_counter)(int idx, u32 val);
void (*start)(void);
void (*stop)(void);
+ void (*reset)(void *);
const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX];
@@ -612,6 +613,19 @@ static struct pmu pmu = {
#include "perf_event_v6.c"
#include "perf_event_v7.c"
+/*
+ * Ensure the PMU has sane values out of reset.
+ * This requires SMP to be available, so exists as a separate initcall.
+ */
+static int __init
+armpmu_reset(void)
+{
+ if (armpmu && armpmu->reset)
+ return on_each_cpu(armpmu->reset, NULL, 1);
+ return 0;
+}
+arch_initcall(armpmu_reset);
+
static int __init
init_hw_perf_events(void)
{
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 2aa83c2..4960686 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -849,6 +849,18 @@ static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
}
}
+static void armv7pmu_reset(void *info)
+{
+ u32 idx, nb_cnt = armpmu->num_events;
+
+ /* The counter and interrupt enable registers are unknown at reset. */
+ for (idx = 1; idx < nb_cnt; ++idx)
+ armv7pmu_disable_event(NULL, idx);
+
+ /* Initialize & Reset PMNC: C and P bits */
+ armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
+}
+
static struct arm_pmu armv7pmu = {
.handle_irq = armv7pmu_handle_irq,
.enable = armv7pmu_enable_event,
@@ -858,17 +870,15 @@ static struct arm_pmu armv7pmu = {
.get_event_idx = armv7pmu_get_event_idx,
.start = armv7pmu_start,
.stop = armv7pmu_stop,
+ .reset = armv7pmu_reset,
.raw_event_mask = 0xFF,
.max_period = (1LLU << 32) - 1,
};
-static u32 __init armv7_reset_read_pmnc(void)
+static u32 __init armv7_read_num_pmnc_events(void)
{
u32 nb_cnt;
- /* Initialize & Reset PMNC: C and P bits */
- armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
-
/* Read the nb of CNTx counters supported from PMNC */
nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
@@ -882,7 +892,7 @@ static const struct arm_pmu *__init armv7_a8_pmu_init(void)
armv7pmu.name = "ARMv7 Cortex-A8";
armv7pmu.cache_map = &armv7_a8_perf_cache_map;
armv7pmu.event_map = &armv7_a8_perf_map;
- armv7pmu.num_events = armv7_reset_read_pmnc();
+ armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
@@ -892,7 +902,7 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
armv7pmu.name = "ARMv7 Cortex-A9";
armv7pmu.cache_map = &armv7_a9_perf_cache_map;
armv7pmu.event_map = &armv7_a9_perf_map;
- armv7pmu.num_events = armv7_reset_read_pmnc();
+ armv7pmu.num_events = armv7_read_num_pmnc_events();
return &armv7pmu;
}
#else
--
1.7.0.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH v2] ARM: perf: reset counters on all CPUs during initialisation
2011-03-23 15:46 [PATCH v2] ARM: perf: reset counters on all CPUs during initialisation Will Deacon
@ 2011-03-24 16:22 ` Will Deacon
[not found] ` <-978680943347076223@unknownmsgid>
1 sibling, 0 replies; 3+ messages in thread
From: Will Deacon @ 2011-03-24 16:22 UTC (permalink / raw)
To: linux-arm-kernel
> ARMv7 dictates that the interrupt-enable and count-enable registers for
> each PMU counter are UNKNOWN following core reset.
>
> This patch adds a new (optional) function pointer to struct arm_pmu for
> resetting the PMU state during init. The reset function is called on
> each CPU via an arch_initcall in the generic ARM perf_event code and
> allows the PMU backend to write sane values to any UNKNOWN registers.
>
> Cc: Jean Pihet <jean.pihet@ti.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
>
> Hi Jean, here's the updated patch following the discussion on the list.
>
> Please let me know what you think.
>
> Will
Resending with correct email address for Jean...
> arch/arm/kernel/perf_event.c | 14 ++++++++++++++
> arch/arm/kernel/perf_event_v7.c | 22 ++++++++++++++++------
> 2 files changed, 30 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
> index 53f6068..b23a364 100644
> --- a/arch/arm/kernel/perf_event.c
> +++ b/arch/arm/kernel/perf_event.c
> @@ -79,6 +79,7 @@ struct arm_pmu {
> void (*write_counter)(int idx, u32 val);
> void (*start)(void);
> void (*stop)(void);
> + void (*reset)(void *);
> const unsigned (*cache_map)[PERF_COUNT_HW_CACHE_MAX]
> [PERF_COUNT_HW_CACHE_OP_MAX]
> [PERF_COUNT_HW_CACHE_RESULT_MAX];
> @@ -612,6 +613,19 @@ static struct pmu pmu = {
> #include "perf_event_v6.c"
> #include "perf_event_v7.c"
>
> +/*
> + * Ensure the PMU has sane values out of reset.
> + * This requires SMP to be available, so exists as a separate initcall.
> + */
> +static int __init
> +armpmu_reset(void)
> +{
> + if (armpmu && armpmu->reset)
> + return on_each_cpu(armpmu->reset, NULL, 1);
> + return 0;
> +}
> +arch_initcall(armpmu_reset);
> +
> static int __init
> init_hw_perf_events(void)
> {
> diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
> index 2aa83c2..4960686 100644
> --- a/arch/arm/kernel/perf_event_v7.c
> +++ b/arch/arm/kernel/perf_event_v7.c
> @@ -849,6 +849,18 @@ static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
> }
> }
>
> +static void armv7pmu_reset(void *info)
> +{
> + u32 idx, nb_cnt = armpmu->num_events;
> +
> + /* The counter and interrupt enable registers are unknown at reset. */
> + for (idx = 1; idx < nb_cnt; ++idx)
> + armv7pmu_disable_event(NULL, idx);
> +
> + /* Initialize & Reset PMNC: C and P bits */
> + armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
> +}
> +
> static struct arm_pmu armv7pmu = {
> .handle_irq = armv7pmu_handle_irq,
> .enable = armv7pmu_enable_event,
> @@ -858,17 +870,15 @@ static struct arm_pmu armv7pmu = {
> .get_event_idx = armv7pmu_get_event_idx,
> .start = armv7pmu_start,
> .stop = armv7pmu_stop,
> + .reset = armv7pmu_reset,
> .raw_event_mask = 0xFF,
> .max_period = (1LLU << 32) - 1,
> };
>
> -static u32 __init armv7_reset_read_pmnc(void)
> +static u32 __init armv7_read_num_pmnc_events(void)
> {
> u32 nb_cnt;
>
> - /* Initialize & Reset PMNC: C and P bits */
> - armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
> -
> /* Read the nb of CNTx counters supported from PMNC */
> nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
>
> @@ -882,7 +892,7 @@ static const struct arm_pmu *__init armv7_a8_pmu_init(void)
> armv7pmu.name = "ARMv7 Cortex-A8";
> armv7pmu.cache_map = &armv7_a8_perf_cache_map;
> armv7pmu.event_map = &armv7_a8_perf_map;
> - armv7pmu.num_events = armv7_reset_read_pmnc();
> + armv7pmu.num_events = armv7_read_num_pmnc_events();
> return &armv7pmu;
> }
>
> @@ -892,7 +902,7 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
> armv7pmu.name = "ARMv7 Cortex-A9";
> armv7pmu.cache_map = &armv7_a9_perf_cache_map;
> armv7pmu.event_map = &armv7_a9_perf_map;
> - armv7pmu.num_events = armv7_reset_read_pmnc();
> + armv7pmu.num_events = armv7_read_num_pmnc_events();
> return &armv7pmu;
> }
> #else
> --
> 1.7.0.4
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH v2] ARM: perf: reset counters on all CPUs during initialisation
[not found] ` <-978680943347076223@unknownmsgid>
@ 2011-03-25 10:10 ` Jean Pihet
0 siblings, 0 replies; 3+ messages in thread
From: Jean Pihet @ 2011-03-25 10:10 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, Mar 24, 2011 at 5:22 PM, Will Deacon <will.deacon@arm.com> wrote:
>> ARMv7 dictates that the interrupt-enable and count-enable registers for
>> each PMU counter are UNKNOWN following core reset.
>>
>> This patch adds a new (optional) function pointer to struct arm_pmu for
>> resetting the PMU state during init. The reset function is called on
>> each CPU via an arch_initcall in the generic ARM perf_event code and
>> allows the PMU backend to write sane values to any UNKNOWN registers.
>>
>> Cc: Jean Pihet <jean.pihet@ti.com>
>> Signed-off-by: Will Deacon <will.deacon@arm.com>
>> ---
>>
>> Hi Jean, here's the updated patch following the discussion on the list.
>>
>> Please let me know what you think.
Great work, thanks!
Acked-by: j-pihet at ti.com
(Please note the correct e-mail address ;-)
Regards,
Jean
>>
>> Will
>
> Resending with correct email address for Jean...
>
>> ?arch/arm/kernel/perf_event.c ? ?| ? 14 ++++++++++++++
>> ?arch/arm/kernel/perf_event_v7.c | ? 22 ++++++++++++++++------
>> ?2 files changed, 30 insertions(+), 6 deletions(-)
>>
>> diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
>> index 53f6068..b23a364 100644
>> --- a/arch/arm/kernel/perf_event.c
>> +++ b/arch/arm/kernel/perf_event.c
>> @@ -79,6 +79,7 @@ struct arm_pmu {
>> ? ? ? void ? ? ? ? ? ?(*write_counter)(int idx, u32 val);
>> ? ? ? void ? ? ? ? ? ?(*start)(void);
>> ? ? ? void ? ? ? ? ? ?(*stop)(void);
>> + ? ? void ? ? ? ? ? ?(*reset)(void *);
>> ? ? ? const unsigned ?(*cache_map)[PERF_COUNT_HW_CACHE_MAX]
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [PERF_COUNT_HW_CACHE_OP_MAX]
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [PERF_COUNT_HW_CACHE_RESULT_MAX];
>> @@ -612,6 +613,19 @@ static struct pmu pmu = {
>> ?#include "perf_event_v6.c"
>> ?#include "perf_event_v7.c"
>>
>> +/*
>> + * Ensure the PMU has sane values out of reset.
>> + * This requires SMP to be available, so exists as a separate initcall.
>> + */
>> +static int __init
>> +armpmu_reset(void)
>> +{
>> + ? ? if (armpmu && armpmu->reset)
>> + ? ? ? ? ? ? return on_each_cpu(armpmu->reset, NULL, 1);
>> + ? ? return 0;
>> +}
>> +arch_initcall(armpmu_reset);
>> +
>> ?static int __init
>> ?init_hw_perf_events(void)
>> ?{
>> diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
>> index 2aa83c2..4960686 100644
>> --- a/arch/arm/kernel/perf_event_v7.c
>> +++ b/arch/arm/kernel/perf_event_v7.c
>> @@ -849,6 +849,18 @@ static int armv7pmu_get_event_idx(struct cpu_hw_events *cpuc,
>> ? ? ? }
>> ?}
>>
>> +static void armv7pmu_reset(void *info)
>> +{
>> + ? ? u32 idx, nb_cnt = armpmu->num_events;
>> +
>> + ? ? /* The counter and interrupt enable registers are unknown at reset. */
>> + ? ? for (idx = 1; idx < nb_cnt; ++idx)
>> + ? ? ? ? ? ? armv7pmu_disable_event(NULL, idx);
>> +
>> + ? ? /* Initialize & Reset PMNC: C and P bits */
>> + ? ? armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
>> +}
>> +
>> ?static struct arm_pmu armv7pmu = {
>> ? ? ? .handle_irq ? ? ? ? ? ? = armv7pmu_handle_irq,
>> ? ? ? .enable ? ? ? ? ? ? ? ? = armv7pmu_enable_event,
>> @@ -858,17 +870,15 @@ static struct arm_pmu armv7pmu = {
>> ? ? ? .get_event_idx ? ? ? ? ?= armv7pmu_get_event_idx,
>> ? ? ? .start ? ? ? ? ? ? ? ? ?= armv7pmu_start,
>> ? ? ? .stop ? ? ? ? ? ? ? ? ? = armv7pmu_stop,
>> + ? ? .reset ? ? ? ? ? ? ? ? ?= armv7pmu_reset,
>> ? ? ? .raw_event_mask ? ? ? ? = 0xFF,
>> ? ? ? .max_period ? ? ? ? ? ? = (1LLU << 32) - 1,
>> ?};
>>
>> -static u32 __init armv7_reset_read_pmnc(void)
>> +static u32 __init armv7_read_num_pmnc_events(void)
>> ?{
>> ? ? ? u32 nb_cnt;
>>
>> - ? ? /* Initialize & Reset PMNC: C and P bits */
>> - ? ? armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
>> -
>> ? ? ? /* Read the nb of CNTx counters supported from PMNC */
>> ? ? ? nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
>>
>> @@ -882,7 +892,7 @@ static const struct arm_pmu *__init armv7_a8_pmu_init(void)
>> ? ? ? armv7pmu.name ? ? ? ? ? = "ARMv7 Cortex-A8";
>> ? ? ? armv7pmu.cache_map ? ? ?= &armv7_a8_perf_cache_map;
>> ? ? ? armv7pmu.event_map ? ? ?= &armv7_a8_perf_map;
>> - ? ? armv7pmu.num_events ? ? = armv7_reset_read_pmnc();
>> + ? ? armv7pmu.num_events ? ? = armv7_read_num_pmnc_events();
>> ? ? ? return &armv7pmu;
>> ?}
>>
>> @@ -892,7 +902,7 @@ static const struct arm_pmu *__init armv7_a9_pmu_init(void)
>> ? ? ? armv7pmu.name ? ? ? ? ? = "ARMv7 Cortex-A9";
>> ? ? ? armv7pmu.cache_map ? ? ?= &armv7_a9_perf_cache_map;
>> ? ? ? armv7pmu.event_map ? ? ?= &armv7_a9_perf_map;
>> - ? ? armv7pmu.num_events ? ? = armv7_reset_read_pmnc();
>> + ? ? armv7pmu.num_events ? ? = armv7_read_num_pmnc_events();
>> ? ? ? return &armv7pmu;
>> ?}
>> ?#else
>> --
>> 1.7.0.4
>
>
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-03-25 10:10 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-23 15:46 [PATCH v2] ARM: perf: reset counters on all CPUs during initialisation Will Deacon
2011-03-24 16:22 ` Will Deacon
[not found] ` <-978680943347076223@unknownmsgid>
2011-03-25 10:10 ` Jean Pihet
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).