perf: arm: enable pmuserenr [1/1]

PD#SWPL-4673

Problem:
userspace can't access perf monitor cnt with "mrc ... c9,c13,0"

Solution:
actually userspace should check perf monitor cnt access permissions first
before use, so this is a workround.
enable pmuserenr with "mcr ... c9,c14,0" in several places:
1, perf probe
2, cpu idle (state>0) exit
3, cpu online
4, system resume after suspend

Verify:
u212

Change-Id: Ib09682d1d47545dfef8b088283ddbbf390630d3e
Signed-off-by: Hanjie Lin <hanjie.lin@amlogic.com>
This commit is contained in:
Hanjie Lin
2019-02-18 20:03:16 +08:00
committed by Jianxin Pan
parent 56f8ec1578
commit a3d9f54206
3 changed files with 108 additions and 1 deletions

View File

@@ -29,4 +29,9 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
(regs)->ARM_sp = current_stack_pointer; \
(regs)->ARM_cpsr = SVC_MODE; \
}
#ifdef CONFIG_AMLOGIC_MODIFY
void enable_pmuserenr(void);
#endif
#endif /* __ARM_PERF_EVENT_H__ */

View File

@@ -13,6 +13,9 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <asm/cpuidle.h>
#ifdef CONFIG_AMLOGIC_MODIFY
#include <asm/perf_event.h>
#endif
extern struct of_cpuidle_method __cpuidle_method_of_table[];
@@ -51,9 +54,22 @@ int arm_cpuidle_simple_enter(struct cpuidle_device *dev,
*/
int arm_cpuidle_suspend(int index)
{
#ifdef CONFIG_AMLOGIC_MODIFY
int ret;
int cpu = smp_processor_id();
ret = cpuidle_ops[cpu].suspend(index);
if (index > 0) {
pr_debug("arm_cpuidle_suspend(%d) exit\n", index);
enable_pmuserenr();
}
return ret;
#else
int cpu = smp_processor_id();
return cpuidle_ops[cpu].suspend(index);
#endif
}
/**
@@ -135,7 +151,7 @@ static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
* this cpu,
* -ENOENT if it fails to find an 'enable-method' property,
* -ENXIO if the HW reports a failure or a misconfiguration,
* -ENOMEM if the HW report an memory allocation failure
* -ENOMEM if the HW report an memory allocation failure
*/
int __init arm_cpuidle_init(int cpu)
{

View File

@@ -28,6 +28,10 @@
#include <linux/perf/arm_pmu.h>
#include <linux/platform_device.h>
#ifdef CONFIG_AMLOGIC_MODIFY
#include <asm/perf_event.h>
#endif
/*
* Common ARMv7 event types
*
@@ -2038,8 +2042,86 @@ static const struct pmu_probe_info armv7_pmu_probe_table[] = {
{ /* sentinel value */ }
};
#ifdef CONFIG_AMLOGIC_MODIFY
#if 0
static int read_pmuserenr(void)
{
int val = -1;
asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (val):: "memory");
return val;
}
#endif
void enable_pmuserenr(void)
{
//pr_emerg("enable_pmuserenr() start, val = %d\n", read_pmuserenr());
asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (1) : "memory");
//pr_emerg("enable_pmuserenr() end, val = %d\n", read_pmuserenr());
}
static void enable_pmuserenr_single(void *info)
{
enable_pmuserenr();
}
static void enable_pmuserenr_all(void)
{
pr_info("enable_pmuserenr_all() start\n");
enable_pmuserenr_single(NULL);
smp_call_function_many(cpu_possible_mask,
enable_pmuserenr_single,
NULL,
1);
pr_info("enable_pmuserenr_all() end\n");
}
static int pmu_user_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
{
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
pr_debug("cpu online callback\n");
enable_pmuserenr();
break;
default:
break;
}
return NOTIFY_OK;
}
static struct notifier_block pmu_user_notify = {
&pmu_user_callback,
NULL,
0
};
static int armv7_pmu_resume(struct platform_device *pdev)
{
pr_debug("armv7_pmu_resume()\n");
enable_pmuserenr();
return 0;
}
static int armv7_pmu_suspend(struct platform_device *pdev,
pm_message_t state)
{
pr_debug("armv7_pmu_suspend()\n");
return 0;
}
#endif
static int armv7_pmu_device_probe(struct platform_device *pdev)
{
#ifdef CONFIG_AMLOGIC_MODIFY
enable_pmuserenr_all();
__register_cpu_notifier(&pmu_user_notify);
#endif
return arm_pmu_device_probe(pdev, armv7_pmu_of_device_ids,
armv7_pmu_probe_table);
}
@@ -2050,6 +2132,10 @@ static struct platform_driver armv7_pmu_driver = {
.of_match_table = armv7_pmu_of_device_ids,
},
.probe = armv7_pmu_device_probe,
#ifdef CONFIG_AMLOGIC_MODIFY
.suspend = armv7_pmu_suspend,
.resume = armv7_pmu_resume,
#endif
};
static int __init register_armv7_pmu_driver(void)