mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 20:07:46 +09:00
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:
@@ -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__ */
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user