【发布时间】:2018-07-23 17:04:27
【问题描述】:
我正在尝试遵循这些说明:
我的目标是为 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:/ # cat /proc/modules
read_arm_pmu 16384 0 - 实时 0x0000000000000000 (PO)
enable_arm_pmu 16384 0 - 实时 0x0000000000000000 (PO)
juno:/ # cat /proc/devices
字符设备: 1 个内存 5 /dev/tty 5 /开发/控制台 5 /dev/ptmx 10 杂项 13输入 14声 29 脸书 90 吨 108 pp 第116章 128 分 136 分 180个USB 第189章 第204章 226 平方米 第249章 250 抽头 第251话 252 三通 253 实时时钟 254gpio芯片
块设备: 1 个虚拟磁盘 第259章 7 循环 8 标准差 31 mtdblock 65 标准差 66 标准差 67 标准差 68 标准差 69 标准差 70 标准差 71 标准差 128 标准差 129 标准差 130 标准差 131 标准差 132 标准差 133 标准差 134 标准差 135 标准差 179毫米 253 设备映射器 第254章
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级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 - 内核模块应该启用用户空间访问,但它不工作。寻求帮助以了解原因。
谢谢, 路易斯
编辑:格式化,让我的问题更清晰。
【问题讨论】:
标签: module linux-kernel arm arm64 illegal-instruction