我正在尝试遵循以下说明:
我的目标是为 PMU 启用用户空间访问。这些是我正在使用的模块的一些说明。
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);
输出(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
接下来是第二个模块,这次只读取寄存器中的值。
模块(测试它是否保留寄存器上的值):
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);
输出(dmesg):
[79385.429198] \x0aPMCR_EL0 register : 41023040
[79385.434584] \x0aPMUSERENR register : 0
用一个简单的程序测试用户空间的功能给出:
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
注意:我知道这可能是因为 PMCR_EL0 的第一位是 0 而 PMUSERENR 不是 f。不知道如何做到这一点,以便模块不会更改寄存器中的值...
可能有助于调试的有用命令:
juno:/ # 猫 /proc/modules
read_arm_pmu 16384 0 - 实时 0x0000000000000000 (PO)
enable_arm_pmu 16384 0 - 实时 0x0000000000000000 (PO)
juno:/ # 猫 /proc/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 三通 253 rtc 254 gpiochip
块设备: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 134 134 sd 134 sd 134 sd 134 sd 134个设备虚拟块
猫/proc/sys/内核/污染
4097
juno:/ # cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5
2:1844410 1197983 1353732 16779 3199 5419 GIC v2 92级arch_mem_timer
3:0 0 0 0 0 0 GIC v2 29 级arch_timer
4:894927 272142 288023 18616 39333 15390 GIC v2 30级arch_timer
7: 0 0 0 0 0 0 GIC v2 198 电平定时器
14:419017 0 0 0 0 0 GIC v2 68 级别 mhu_link
15:0 0 0 0 0 0 GIC v2 67 级别 mhu_link
16:0 0 0 0 0 0 GIC v2 120 级别 7ff00000.dma
17:0 0 0 0 0 0 GIC v2 121 级别 7ff00000.dma
18:0 0 0 0 0 0 GIC v2 122 级别 7ff00000.dma
19:0 0 0 0 0 0 GIC v2 123 级别 7ff00000.dma
20:0 0 0 0 0 0 GIC v2 124 级别 7ff00000.dma
21:0 0 0 0 0 0 GIC v2 140 级别 7ff00000.dma
22:0 0 0 0 0 0 GIC v2 141 级别 7ff00000.dma
23:0 0 0 0 0 0 GIC v2 142 级别 7ff00000.dma
24:0 0 0 0 0 0 GIC v2 143 级别 7ff00000.dma
25:0 0 0 0 0 0 GIC v2 125 级 hdlcd
26:0 0 0 0 0 0 GIC v2 117 级别 hdlcd
27: 6336 0 0 0 0 0 GIC v2 115 级 uart-pl011
28: 53666 0 0 0 0 0 GIC v2 136 级别 7ffa0000.i2c
30: 47345 0 0 0 0 0 GIC v2 149 级别 ehci_hcd:usb1
33:14370 0 0 0 0 0 GIC v2 65 级别 2d000000.gpu
34:0 0 0 0 0 0 GIC v2 66 级 2d000000.gpu
35:39222 0 0 0 0 0 GIC v2 64 级 2d000000.gpu
37: 52 0 0 0 0 0 GIC v2 194 级别 mmci-pl18x (cmd)
40:0 0 0 0 0 0 GIC v2 100 级别 rtc-pl031
43:0 0 0 0 0 0 GIC v2 169 级别 sata_sil24[0000:03:00.0]
45:0 0 0 0 0 0 M SI 0 边缘 PCIe PME,aerdrv
52: 1049234 0 0 0 0 0 M SI 4194304 边缘 eth0
IPI0: 62569 1835646 1888285 43688 29194 29798 重新调度中断
IPI1:315 1276 725 386 307 207 函数调用中断
IPI2:0 0 0 0 0 0 C PU 停止中断
IPI3:829962 24938 62500 1274 498 1029 定时器广播中断
IPI4:800250 925302 1266671 10821 9264 7192 I RQ 工作中断
IPI5:0 0 0 0 0 0 C PU 唤醒中断
错误:0
我希望你们能帮助我,感觉我在一些可能很简单的事情上浪费了很多时间。
TLDR - 内核模块应该启用用户空间访问,但它不工作。寻求帮助以了解原因。
谢谢,路易斯
编辑:格式化,让我的问题更清楚。