|
@@ -678,6 +678,28 @@ static void armv8pmu_disable_event(struct perf_event *event)
|
|
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
|
raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void armv8pmu_start(struct arm_pmu *cpu_pmu)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
|
|
|
+
|
|
|
|
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
|
|
|
+ /* Enable all counters */
|
|
|
|
+ armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMU_PMCR_E);
|
|
|
|
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void armv8pmu_stop(struct arm_pmu *cpu_pmu)
|
|
|
|
+{
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
|
|
|
+
|
|
|
|
+ raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
|
|
|
+ /* Disable all counters */
|
|
|
|
+ armv8pmu_pmcr_write(armv8pmu_pmcr_read() & ~ARMV8_PMU_PMCR_E);
|
|
|
|
+ raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
|
static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
|
{
|
|
{
|
|
u32 pmovsr;
|
|
u32 pmovsr;
|
|
@@ -702,6 +724,11 @@ static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
|
*/
|
|
*/
|
|
regs = get_irq_regs();
|
|
regs = get_irq_regs();
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Stop the PMU while processing the counter overflows
|
|
|
|
+ * to prevent skews in group events.
|
|
|
|
+ */
|
|
|
|
+ armv8pmu_stop(cpu_pmu);
|
|
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
|
|
for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
|
|
struct perf_event *event = cpuc->events[idx];
|
|
struct perf_event *event = cpuc->events[idx];
|
|
struct hw_perf_event *hwc;
|
|
struct hw_perf_event *hwc;
|
|
@@ -726,6 +753,7 @@ static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
|
if (perf_event_overflow(event, &data, regs))
|
|
if (perf_event_overflow(event, &data, regs))
|
|
cpu_pmu->disable(event);
|
|
cpu_pmu->disable(event);
|
|
}
|
|
}
|
|
|
|
+ armv8pmu_start(cpu_pmu);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Handle the pending perf events.
|
|
* Handle the pending perf events.
|
|
@@ -739,28 +767,6 @@ static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu)
|
|
return IRQ_HANDLED;
|
|
return IRQ_HANDLED;
|
|
}
|
|
}
|
|
|
|
|
|
-static void armv8pmu_start(struct arm_pmu *cpu_pmu)
|
|
|
|
-{
|
|
|
|
- unsigned long flags;
|
|
|
|
- struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
|
|
|
-
|
|
|
|
- raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
|
|
|
- /* Enable all counters */
|
|
|
|
- armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMU_PMCR_E);
|
|
|
|
- raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void armv8pmu_stop(struct arm_pmu *cpu_pmu)
|
|
|
|
-{
|
|
|
|
- unsigned long flags;
|
|
|
|
- struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
|
|
|
|
-
|
|
|
|
- raw_spin_lock_irqsave(&events->pmu_lock, flags);
|
|
|
|
- /* Disable all counters */
|
|
|
|
- armv8pmu_pmcr_write(armv8pmu_pmcr_read() & ~ARMV8_PMU_PMCR_E);
|
|
|
|
- raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
|
|
static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
|
|
struct perf_event *event)
|
|
struct perf_event *event)
|
|
{
|
|
{
|