c - ARM架构中如何读取协处理器寄存器

标签 c assembly arm

我正在尝试读取以下片上系统中的 CP15 协处理器

皮质 A7 - ARMv7-A

在我的代码段下方

void main (void)
{
    unsigned int reg_value = 0;
    asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(reg_value) );
    printf("reg_value: %d", reg_value);
}

我不知道这是否是读取协处理器寄存器的正确方法,但它的编译已完成且没有错误。 执行过程中出现问题(代码在root下执行):

Illegal instruction

如果我使用 gdb,我会得到以下结果:

   0x000086a0 <+16>:    str r3, [r11, #-40] ; 0x28
=> 0x000086a4 <+20>:    mrc 15, 0, r3, cr0, cr0, {0}
   0x000086a8 <+24>:    str r3, [r11, #-40] ; 0x28

为什么我无法读取协处理器寄存器?我的代码有什么问题?

最佳答案

看来您正在尝试使用指令访问 MIDR:Main ID Register(来自 ARMARMv7 B4.1.105)

MRC p15, 0, <Rt>, c0, c0, 0    ; Read MIDR into Rt

但是,当您在 Linux 中执行应用程序时,您处于用户模式 ​​(PL0) 而 ARMARMv7 在 MIDR 的使用约束中指定

Only accessible from PL1 or higher.

因此只能在 PL1、PL2、PL3 访问。要访问它,您需要创建一个运行在 PL1 上的驱动程序,它将读取 MIDR。然后,在您的应用程序中,打开此驱动程序以使用 IOCTL 等方式获取数据。

您也可以尝试使用来自 PL0 的 SVC 调用访问内核模式 (PL1),但这意味着修改您的内核 SVC 处理程序。

关于c - ARM架构中如何读取协处理器寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49051641/

相关文章:

c - double 的绝对值

linux - 在 ARM-OABI 上实现 syscall()。什么是 "svc#0x900071"?

c - 获取 AIX 上正在运行的进程的可执行文件的完整路径

linux - 如何更改 gcc 生成的 asm 代码的入口点?

c++ - 编译器在这里生成的汇编代码中的寻址模式是什么?

arm - GNU ARM 汇编器上的意外警告

c - 将加密加速单元与 uclinux 和外部库结合使用

c - libc 函数 isatty() 是如何工作的?

c++ - OpenSSL AES 仅适用于某些机器,即使使用静态链接也是如此

c - memset() 是否比 C 中的 for 循环更有效?