0
votes

I need to implement a kernel module that involves reading the ARM Cortex-A9 coprocessor's register:

register int reg asm ("r6");
reg = -2;
volatile printk(KERN_INFO "reg: %d\n", reg);
volatile  asm("MRC p15, 0,r6, c1, c0, 2;"); //Read Coprocessor Access Control Register
volatile  printk(KERN_INFO "reg: %d\n", reg);

However, when i run this on QEMU, it always print out:

reg: -2
reg: -2

Is this because of my code or is it because of QEMU?

Thanks in advance.

1
Also the to check qemu implementation status of particular CP register, you need to grep qemu sources for that register name, there is many ARMCPRegInfo data structures defined here, and also a bunch of logic to work with, all writen in C. So, for example, to deal with "Read Coprocessor Access Control Register" grep for "CPACR".Jettatura

1 Answers

1
votes

Your code should work fine (though you need to remove volatile from printk lines, and ASM command should be asm volatile, not the other way around). Try to check next things:

  1. QEMU version. I'm using 2.12 and your code works. So if you're using older version, try 2.12 too.
  2. Emulated machine and cpu. Not sure if it affects CP registers, but I'm using "virt" machine with no CPU specified, you can try this configuration too.
  3. If this doesn't help, check more details about my configuration below.

My configuration

I'm using next command to run QEMU:

$ qemu-system-arm -kernel $zimage -initrd $rootfs \
    -machine virt -nographic -m 512 \
    --append "root=/dev/ram0 rw console=ttyAMA0,115200 mem=512M"

where:

  • $zimage is path to zImage file (my kernel is linux-mainline on tag v4.18, built with multi_v7_defconfig configuration)
  • $rootfs is path to CPIO archive with minimal BusyBox rootfs

My kernel module code is next:

#include <linux/module.h>

static int __init mrc_init(void)
{
    u32 acr;

    /*
     * Read Coprocessor Access Control Register.
     * See Cortex-A9 TRM for details.
     */
    asm volatile ("mrc p15, 0, %0, c1, c0, 2\n" : "=r" (acr));

    pr_info("ACR = 0x%x\n", acr);

    return 0;
}

static void __exit mrc_exit(void)
{
}

module_init(mrc_init);
module_exit(mrc_exit);

MODULE_AUTHOR("Sam Protsenko");
MODULE_DESCRIPTION("Test MRC on QEMU");
MODULE_LICENSE("GPL");

After loading this module I can see next output in dmesg:

ACR = 0xf00000