Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How read coprocessor registers in ARM architecture

Tags:

c

assembly

arm

I'm trying to read CP15 coprocessor in the following System-on-chip

Cortex A7 - ARMv7-A

Below my snippet

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);
}

I don't know if this is the correct way to read the coprocessor register but its compilation is completed without errors. The problem is arisen during its execution (the code is executed in root):

Illegal instruction

If I use gdb I obtain the following result:

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

Why I'm not able to read coprocessor registers? What's wrong with my code?

like image 257
Alvin Avatar asked Mar 01 '18 14:03

Alvin


1 Answers

It seems that you are trying to access MIDR: Main ID Register (from the ARMARMv7 B4.1.105) using the instruction

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

However, as you are in Linux and executing an application, you are in usermode (PL0) and ARMARMv7 specifies in the usage constraints of MIDR that

Only accessible from PL1 or higher.

So only accessible at PL1, PL2, PL3. To access it you need to create a driver running at PL1 which will do the read of MIDR. Then, in your application, open this driver to get the data using IOCTL for example.

You can also try to access the kernel mode (PL1) using a SVC call from PL0, but this would imply modifying your kernel SVC handler.

like image 187
Stoogy Avatar answered Oct 24 '22 01:10

Stoogy