68 lines
3.8 KiB
C
68 lines
3.8 KiB
C
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/smp.h>
|
|
|
|
#define ARMV8_PMCR_MASK 0x3f
|
|
#define ARMV8_PMCR_E (1 << 0)
|
|
#define ARMV8_PMCR_LC (1 << 6)
|
|
|
|
static inline u32 armv8pmu_pmcr_read(void)
|
|
{
|
|
u64 val = 0;
|
|
asm volatile("mrs %0, pmcr_el0" : "=r" (val));
|
|
return (u32)val;
|
|
}
|
|
static inline void armv8pmu_pmcr_write(u32 val)
|
|
{
|
|
val &= ARMV8_PMCR_MASK;
|
|
isb();
|
|
asm volatile("msr pmcr_el0, %0" : : "r" ((u64)val));
|
|
}
|
|
|
|
static inline long long armv8_read_CNTPCT_EL0(void)
|
|
{
|
|
long long val;
|
|
asm volatile("mrs %0, CNTVCT_EL0" : "=r" (val));
|
|
return val;
|
|
}
|
|
|
|
static void
|
|
enable_cpu_counters(void* data)
|
|
{
|
|
asm volatile("msr pmuserenr_el0, %0" : : "r"(0xf));
|
|
armv8pmu_pmcr_write(ARMV8_PMCR_LC|ARMV8_PMCR_E);
|
|
asm volatile("msr PMCNTENSET_EL0, %0" :: "r" ((u32)(1<<31)));
|
|
armv8pmu_pmcr_write(armv8pmu_pmcr_read() | ARMV8_PMCR_E|ARMV8_PMCR_LC);
|
|
printk("\nCPU:%d ", smp_processor_id());
|
|
}
|
|
|
|
static void
|
|
disable_cpu_counters(void* data)
|
|
{
|
|
printk(KERN_INFO "\ndisabling user-mode PMU access on CPU #%d",
|
|
smp_processor_id());
|
|
|
|
armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E);
|
|
asm volatile("msr pmuserenr_el0, %0" : : "r"((u64)0));
|
|
}
|
|
|
|
static int __init init(void)
|
|
{
|
|
on_each_cpu(enable_cpu_counters, NULL, 1);
|
|
printk(KERN_INFO "Enable Access PMU Initialized");
|
|
return 0;
|
|
}
|
|
|
|
static void __exit fini(void)
|
|
{
|
|
on_each_cpu(disable_cpu_counters, NULL, 1);
|
|
printk(KERN_INFO "Access PMU Disabled");
|
|
}
|
|
|
|
module_init(init);
|
|
module_exit(fini);
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("titan");
|
|
|
|
|