Help module drivers - PMU

From: Luis Martins <hidden>
Date: 2018-08-02 16:03:11

Hi,?

I'm following these instructions:
https://developer.arm.com/products/system-design/cycle-models/knowledge-articles/system-performance-analysis-and-the-arm-performance-monitor-unit

My goal is to enable userspace access for the PMUs. To enable it, I need to configure PMCR_EL0 and PMUSERENR_EL0  using a set of rules defined by ARM.

These are some of the instructions of the module I'm using:
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 \n", smp_processor_id());
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


static void disable_cpu_counters (void* data)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? printk(KERN_INFO "\ndisabling user-mode PMU access on CPU #%d \n",? ? ? ? ? ? ? ? ? ? ? ?
? ? smp_processor_id());
? ? /* Program PMU and disable all counters */? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? armv8pmu_pmcr_write(armv8pmu_pmcr_read() |~ARMV8_PMCR_E);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? asm volatile("msr pmuserenr_el0, %0" ::"r"((u64)0));? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


static int __init init(void)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
{
? ? unsigned int reguser=0;? ? ?


? ? isb();


? ? asm volatile("mrs %0, pmcr_el0" : "=r" (reguser));
? ? printk(KERN_INFO "\nPMCR_EL0 register before : %x\n", reguser);
? ? asm volatile("mrs %0, pmuserenr_el0" : "=r" (reguser));
? ? printk(KERN_INFO "\nPMUSERENR register before : %x\n", reguser);


on_each_cpu (enable_cpu_counters, NULL, 1);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? printk(KERN_INFO "\nEnable Access PMU Initialized\n");


? ? /* Enable counters */
? ? asm volatile("mrs %0, pmcr_el0" : "=r" (reguser));
? ? printk(KERN_INFO "\nPMCR_EL0 register after : %x\n", reguser);
? ? asm volatile("mrs %0, pmuserenr_el0" : "=r" (reguser));
? ? printk(KERN_INFO "\nPMUSERENR register after : %x\n", reguser);


? ? return 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


static void __exit fini(void)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? on_each_cpu(disable_cpu_counters, NULL, 1);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? printk(KERN_INFO "\nAccess PMU Disabled\n");? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


module_init (init);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
module_exit (fini);


Output (dmesg):
[79371.445026] \x0aPMCR_EL0 register before : 41023040
[79371.450997] \x0aPMUSERENR register before : 0
[79371.456511] \x0aCPU:3
[79371.456546] \x0aCPU:2
[79371.456614] \x0aCPU:0
[79371.456631] \x0aCPU:4
[79371.456652] \x0aCPU:5
[79371.473784] \x0aCPU:1
[79371.477254] \x0aEnable Access PMU Initialized
[79371.482693] \x0aPMCR_EL0 register after : 41023001
[79371.488560] \x0aPMUSERENR register after : f


So I can change the value of the registers.

Followed with a second module, this time I'm only interested in reading the values from the registers.


Module (testing if it keeps the values on the registers):
static int __init init(void)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
{? ? ? ??
? ? unsigned int reguser=0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? isb();


? ? /* Enable counters */
? ? asm volatile("mrs %0, pmcr_el0" : "=r" (reguser));
? ? printk(KERN_INFO "\nPMCR_EL0 register : %x\n", reguser);
? ? asm volatile("mrs %0, pmuserenr_el0" : "=r" (reguser));
? ? printk(KERN_INFO "\nPMUSERENR register : %x\n", reguser);


? ? return 0;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


static void __exit fini(void)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? printk(KERN_INFO "\nDisabling read_arm_pmu.ko\n");? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?


module_init (init);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
module_exit (fini);


Output (dmesg):
[79385.429198] \x0aPMCR_EL0 register : 41023040
[79385.434584] \x0aPMUSERENR register : 0


I was expecting that instead of PMCR_EL0 register : 41023040 I would get PMCR_EL0 register : 41023001 and that instead of PMUSERENR register : 0 I would get PMUSERENR register : f.

___________________________

Running:
juno:/ # cat /proc/modules?
read_arm_pmu 16384 0 - Live 0x0000000000000000 (PO)
enable_arm_pmu 16384 0 - Live 0x0000000000000000 (PO)


juno:/ # cat /proc/devices?
Character devices:
1 mem
5 /dev/tty
5 /dev/console
5 /dev/ptmx
10 misc
13 input
14 sound
29 fb
90 mtd
108 ppp
116 alsa
128 ptm
136 pts
180 usb
189 usb_device
204 ttyAMA
226 drm
249 roccat
250 hidraw
251 bsg
252 tee
253 rtc
254 gpiochip


Block devices:
1 ramdisk
259 blkext
7 loop
8 sd
31 mtdblock
65 sd
66 sd
67 sd
68 sd
69 sd
70 sd
71 sd
128 sd
129 sd
130 sd
131 sd
132 sd
133 sd
134 sd
135 sd
179 mmc
253 device-mapper
254 virtblk
___________________________

cat /proc/sys/kernel/tainted
4097
___________________________

juno:/ # cat /proc/interrupts?
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
2: 1844410 1197983 1353732 16779 3199 5419 GIC v2 92 Level arch_mem_timer
3: 0 0 0 0 0 0 GIC v2 29 Level arch_timer
4: 894927 272142 288023 18616 39333 15390 GIC v2 30 Level arch_timer
7: 0 0 0 0 0 0 GIC v2 198 Level timer
14: 419017 0 0 0 0 0 GIC v2 68 Level mhu_link
15: 0 0 0 0 0 0 GIC v2 67 Level mhu_link
16: 0 0 0 0 0 0 GIC v2 120 Level 7ff00000.dma
17: 0 0 0 0 0 0 GIC v2 121 Level 7ff00000.dma
18: 0 0 0 0 0 0 GIC v2 122 Level 7ff00000.dma
19: 0 0 0 0 0 0 GIC v2 123 Level 7ff00000.dma
20: 0 0 0 0 0 0 GIC v2 124 Level 7ff00000.dma
21: 0 0 0 0 0 0 GIC v2 140 Level 7ff00000.dma
22: 0 0 0 0 0 0 GIC v2 141 Level 7ff00000.dma
23: 0 0 0 0 0 0 GIC v2 142 Level 7ff00000.dma
24: 0 0 0 0 0 0 GIC v2 143 Level 7ff00000.dma
25: 0 0 0 0 0 0 GIC v2 125 Level hdlcd
26: 0 0 0 0 0 0 GIC v2 117 Level hdlcd
27: 6336 0 0 0 0 0 GIC v2 115 Level uart-pl011
28: 53666 0 0 0 0 0 GIC v2 136 Level 7ffa0000.i2c
30: 47345 0 0 0 0 0 GIC v2 149 Level ehci_hcd:usb1
33: 14370 0 0 0 0 0 GIC v2 65 Level 2d000000.gpu
34: 0 0 0 0 0 0 GIC v2 66 Level 2d000000.gpu
35: 39222 0 0 0 0 0 GIC v2 64 Level 2d000000.gpu
37: 52 0 0 0 0 0 GIC v2 194 Level mmci-pl18x (cmd)
40: 0 0 0 0 0 0 GIC v2 100 Level rtc-pl031
43: 0 0 0 0 0 0 GIC v2 169 Level sata_sil24[0000:03:00.0]
45: 0 0 0 0 0 0 M SI 0 Edge PCIe PME, aerdrv
52: 1049234 0 0 0 0 0 M SI 4194304 Edge eth0
IPI0: 62569 1835646 1888285 43688 29194 29798 R escheduling interrupts
IPI1: 315 1276 725 386 307 207 F unction call interrupts
IPI2: 0 0 0 0 0 0 C PU stop interrupts
IPI3: 829962 24938 62500 1274 498 1029 T imer broadcast interrupts
IPI4: 800250 925302 1266671 10821 9264 7192 I RQ work interrupts
IPI5: 0 0 0 0 0 0 C PU wake-up interrupts
Err: 0
___________________________

Testing the functionality on userspace with a simple program gives:

juno:/data/data/papi/workplace # ./monitoring 2 2 2 3
[1359092.706711] monitoring[11095]: undefined instruction: pc=000000000040065c
[1359092.713652] Code: 00000000 00000000 00000000 d10043ff (d53b9c00)
Illegal instruction

TLDR - Shouldn't the second module keep the same data as the first module values, since the reading portion of the code is exactly the same?

Thanks,
Luis
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help